UNPKG

mcp-use

Version:

Opinionated MCP Framework for TypeScript (@modelcontextprotocol/sdk compatible) - Build MCP Agents, Clients and Servers with support for ChatGPT Apps, Code Mode, OAuth, Notifications, Sampling, Observability and more.

11,695 lines 417 kB
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
var __esm = (fn, res) => function __init() {
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
};
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// src/logging.ts
function resolveLevel(env) {
  const envValue = typeof process !== "undefined" && process.env ? env : void 0;
  switch (envValue?.trim()) {
    case "2":
      return "debug";
    case "1":
      return "info";
    default:
      return "info";
  }
}
function formatArgs(args) {
  if (args.length === 0) return "";
  return args.map((arg) => {
    if (typeof arg === "string") return arg;
    try {
      return JSON.stringify(arg);
    } catch {
      return String(arg);
    }
  }).join(" ");
}
var DEFAULT_LOGGER_NAME, SimpleConsoleLogger, Logger, logger;
var init_logging = __esm({
  "src/logging.ts"() {
    "use strict";
    DEFAULT_LOGGER_NAME = "mcp-use";
    __name(resolveLevel, "resolveLevel");
    __name(formatArgs, "formatArgs");
    SimpleConsoleLogger = class {
      static {
        __name(this, "SimpleConsoleLogger");
      }
      _level;
      name;
      format;
      constructor(name = DEFAULT_LOGGER_NAME, level = "info", format = "minimal") {
        this.name = name;
        this._level = level;
        this.format = format;
      }
      shouldLog(level) {
        const levels = [
          "error",
          "warn",
          "info",
          "http",
          "verbose",
          "debug",
          "silly"
        ];
        const currentIndex = levels.indexOf(this._level);
        const messageIndex = levels.indexOf(level);
        return messageIndex <= currentIndex;
      }
      formatMessage(level, message, args) {
        const timestamp = (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: false });
        const extraArgs = formatArgs(args);
        const fullMessage = extraArgs ? `${message} ${extraArgs}` : message;
        switch (this.format) {
          case "detailed":
            return `${timestamp} [${this.name}] ${level.toUpperCase()}: ${fullMessage}`;
          case "emoji": {
            const emojiMap = {
              error: "\u274C",
              warn: "\u26A0\uFE0F",
              info: "\u2139\uFE0F",
              http: "\u{1F310}",
              verbose: "\u{1F4DD}",
              debug: "\u{1F50D}",
              silly: "\u{1F92A}"
            };
            return `${timestamp} [${this.name}] ${emojiMap[level] || ""} ${level.toUpperCase()}: ${fullMessage}`;
          }
          case "minimal":
          default:
            return `${timestamp} [${this.name}] ${level}: ${fullMessage}`;
        }
      }
      error(message, ...args) {
        if (this.shouldLog("error")) {
          console.error(this.formatMessage("error", message, args));
        }
      }
      warn(message, ...args) {
        if (this.shouldLog("warn")) {
          console.warn(this.formatMessage("warn", message, args));
        }
      }
      info(message, ...args) {
        if (this.shouldLog("info")) {
          console.info(this.formatMessage("info", message, args));
        }
      }
      debug(message, ...args) {
        if (this.shouldLog("debug")) {
          console.debug(this.formatMessage("debug", message, args));
        }
      }
      http(message, ...args) {
        if (this.shouldLog("http")) {
          console.log(this.formatMessage("http", message, args));
        }
      }
      verbose(message, ...args) {
        if (this.shouldLog("verbose")) {
          console.log(this.formatMessage("verbose", message, args));
        }
      }
      silly(message, ...args) {
        if (this.shouldLog("silly")) {
          console.log(this.formatMessage("silly", message, args));
        }
      }
      get level() {
        return this._level;
      }
      set level(newLevel) {
        this._level = newLevel;
      }
      setFormat(format) {
        this.format = format;
      }
    };
    Logger = class {
      static {
        __name(this, "Logger");
      }
      static instances = {};
      static currentFormat = "minimal";
      static get(name = DEFAULT_LOGGER_NAME) {
        if (!this.instances[name]) {
          const debugEnv = typeof process !== "undefined" && process.env?.DEBUG || void 0;
          this.instances[name] = new SimpleConsoleLogger(
            name,
            resolveLevel(debugEnv),
            this.currentFormat
          );
        }
        return this.instances[name];
      }
      static configure(options = {}) {
        const { level, format = "minimal" } = options;
        const debugEnv = typeof process !== "undefined" && process.env?.DEBUG || void 0;
        const resolvedLevel = level ?? resolveLevel(debugEnv);
        this.currentFormat = format;
        Object.values(this.instances).forEach((logger2) => {
          logger2.level = resolvedLevel;
          logger2.setFormat(format);
        });
      }
      static setDebug(enabled) {
        let level;
        if (enabled === 2 || enabled === true) level = "debug";
        else if (enabled === 1) level = "info";
        else level = "info";
        Object.values(this.instances).forEach((logger2) => {
          logger2.level = level;
        });
        if (typeof process !== "undefined" && process.env) {
          process.env.DEBUG = enabled ? enabled === true ? "2" : String(enabled) : "0";
        }
      }
      static setFormat(format) {
        this.currentFormat = format;
        this.configure({ format });
      }
    };
    logger = Logger.get();
  }
});

// src/observability/langfuse.ts
var langfuse_exports = {};
__export(langfuse_exports, {
  initializeLangfuse: () => initializeLangfuse,
  langfuseClient: () => langfuseClient,
  langfuseHandler: () => langfuseHandler,
  langfuseInitPromise: () => langfuseInitPromise
});
function getEnvVar(key) {
  if (typeof process !== "undefined" && process.env) {
    return process.env[key];
  }
  return void 0;
}
async function initializeLangfuse(agentId, metadata, metadataProvider, tagsProvider) {
  try {
    const langfuseModule = await import("langfuse-langchain").catch(() => null);
    if (!langfuseModule) {
      logger.debug(
        "Langfuse package not installed - tracing disabled. Install with: npm install @langfuse/langchain"
      );
      return;
    }
    const { CallbackHandler } = langfuseModule;
    class LoggingCallbackHandler extends CallbackHandler {
      static {
        __name(this, "LoggingCallbackHandler");
      }
      agentId;
      metadata;
      metadataProvider;
      tagsProvider;
      verbose;
      constructor(config2, agentId2, metadata2, metadataProvider2, tagsProvider2) {
        super(config2);
        this.agentId = agentId2;
        this.metadata = metadata2;
        this.metadataProvider = metadataProvider2;
        this.tagsProvider = tagsProvider2;
        this.verbose = config2?.verbose ?? false;
      }
      // Override to add custom metadata to traces
      async handleChainStart(chain, inputs, runId, parentRunId, tags, metadata2, name, kwargs) {
        logger.debug("Langfuse: Chain start intercepted");
        const customTags = this.getCustomTags();
        const metadataToAdd = this.getMetadata();
        const enhancedTags = [...tags || [], ...customTags];
        const enhancedMetadata = { ...metadata2 || {}, ...metadataToAdd };
        if (this.verbose) {
          logger.debug(
            `Langfuse: Chain start with custom tags: ${JSON.stringify(enhancedTags)}`
          );
          logger.debug(
            `Langfuse: Chain start with metadata: ${JSON.stringify(enhancedMetadata)}`
          );
        }
        return super.handleChainStart(
          chain,
          inputs,
          runId,
          parentRunId,
          enhancedTags,
          enhancedMetadata,
          name,
          kwargs
        );
      }
      // Get custom tags based on environment and agent configuration
      getCustomTags() {
        const tags = [];
        const env = this.getEnvironmentTag();
        if (env) {
          tags.push(`env:${env}`);
        }
        if (this.agentId) {
          tags.push(`agent_id:${this.agentId}`);
        }
        if (this.tagsProvider) {
          const providerTags = this.tagsProvider();
          if (providerTags && providerTags.length > 0) {
            tags.push(...providerTags);
          }
        }
        return tags;
      }
      // Get metadata
      getMetadata() {
        const metadata2 = {};
        const env = this.getEnvironmentTag();
        if (env) {
          metadata2.env = env;
        }
        if (this.agentId) {
          metadata2.agent_id = this.agentId;
        }
        if (this.metadata) {
          Object.assign(metadata2, this.metadata);
        }
        if (this.metadataProvider) {
          const dynamicMetadata = this.metadataProvider();
          if (dynamicMetadata) {
            Object.assign(metadata2, dynamicMetadata);
          }
        }
        return metadata2;
      }
      // Determine environment tag based on MCP_USE_AGENT_ENV
      getEnvironmentTag() {
        const agentEnv = getEnvVar("MCP_USE_AGENT_ENV");
        if (!agentEnv) {
          return "unknown";
        }
        const envLower = agentEnv.toLowerCase();
        if (envLower === "local" || envLower === "development") {
          return "local";
        } else if (envLower === "production" || envLower === "prod") {
          return "production";
        } else if (envLower === "staging" || envLower === "stage") {
          return "staging";
        } else if (envLower === "hosted" || envLower === "cloud") {
          return "hosted";
        }
        return envLower.replace(/[^a-z0-9_-]/g, "_");
      }
      async handleLLMStart(...args) {
        logger.debug("Langfuse: LLM start intercepted");
        if (this.verbose) {
          logger.debug(`Langfuse: LLM start args: ${JSON.stringify(args)}`);
        }
        return super.handleLLMStart(...args);
      }
      async handleToolStart(...args) {
        logger.debug("Langfuse: Tool start intercepted");
        if (this.verbose) {
          logger.debug(`Langfuse: Tool start args: ${JSON.stringify(args)}`);
        }
        return super.handleToolStart(...args);
      }
      async handleRetrieverStart(...args) {
        logger.debug("Langfuse: Retriever start intercepted");
        if (this.verbose) {
          logger.debug(
            `Langfuse: Retriever start args: ${JSON.stringify(args)}`
          );
        }
        return super.handleRetrieverStart(...args);
      }
      async handleAgentAction(...args) {
        logger.debug("Langfuse: Agent action intercepted");
        if (this.verbose) {
          logger.debug(`Langfuse: Agent action args: ${JSON.stringify(args)}`);
        }
        return super.handleAgentAction(...args);
      }
      async handleAgentEnd(...args) {
        logger.debug("Langfuse: Agent end intercepted");
        if (this.verbose) {
          logger.debug(`Langfuse: Agent end args: ${JSON.stringify(args)}`);
        }
        return super.handleAgentEnd(...args);
      }
    }
    const initialMetadata = metadata || (metadataProvider ? metadataProvider() : {});
    const initialTags = tagsProvider ? tagsProvider() : [];
    const config = {
      publicKey: getEnvVar("LANGFUSE_PUBLIC_KEY"),
      secretKey: getEnvVar("LANGFUSE_SECRET_KEY"),
      baseUrl: getEnvVar("LANGFUSE_HOST") || getEnvVar("LANGFUSE_BASEURL") || "https://cloud.langfuse.com",
      flushAt: Number.parseInt(getEnvVar("LANGFUSE_FLUSH_AT") || "15"),
      flushInterval: Number.parseInt(
        getEnvVar("LANGFUSE_FLUSH_INTERVAL") || "10000"
      ),
      release: getEnvVar("LANGFUSE_RELEASE"),
      requestTimeout: Number.parseInt(
        getEnvVar("LANGFUSE_REQUEST_TIMEOUT") || "10000"
      ),
      enabled: getEnvVar("LANGFUSE_ENABLED") !== "false",
      // Set trace name - can be customized via metadata.trace_name or defaults to 'mcp-use-agent'
      traceName: initialMetadata.trace_name || getEnvVar("LANGFUSE_TRACE_NAME") || "mcp-use-agent",
      // Pass sessionId, userId, and tags to the handler
      sessionId: initialMetadata.session_id || void 0,
      userId: initialMetadata.user_id || void 0,
      tags: initialTags.length > 0 ? initialTags : void 0,
      metadata: initialMetadata || void 0
    };
    logger.debug(
      "Langfuse handler config:",
      JSON.stringify(
        {
          traceName: config.traceName,
          sessionId: config.sessionId,
          userId: config.userId,
          tags: config.tags
        },
        null,
        2
      )
    );
    langfuseState.handler = new LoggingCallbackHandler(
      config,
      agentId,
      metadata,
      metadataProvider,
      tagsProvider
    );
    logger.debug(
      "Langfuse observability initialized successfully with logging enabled"
    );
    try {
      const langfuseCore = await import("langfuse").catch(() => null);
      if (langfuseCore) {
        const { Langfuse } = langfuseCore;
        langfuseState.client = new Langfuse({
          publicKey: getEnvVar("LANGFUSE_PUBLIC_KEY"),
          secretKey: getEnvVar("LANGFUSE_SECRET_KEY"),
          baseUrl: getEnvVar("LANGFUSE_HOST") || "https://cloud.langfuse.com"
        });
        logger.debug("Langfuse client initialized");
      }
    } catch (error) {
      logger.debug(`Langfuse client initialization failed: ${error}`);
    }
  } catch (error) {
    logger.debug(`Langfuse initialization error: ${error}`);
  }
}
var langfuseDisabled, langfuseState, langfuseHandler, langfuseClient, langfuseInitPromise;
var init_langfuse = __esm({
  "src/observability/langfuse.ts"() {
    "use strict";
    init_logging();
    __name(getEnvVar, "getEnvVar");
    langfuseDisabled = getEnvVar("MCP_USE_LANGFUSE")?.toLowerCase() === "false";
    langfuseState = {
      handler: null,
      client: null,
      initPromise: null
    };
    __name(initializeLangfuse, "initializeLangfuse");
    if (langfuseDisabled) {
      logger.debug(
        "Langfuse tracing disabled via MCP_USE_LANGFUSE environment variable"
      );
    } else if (!getEnvVar("LANGFUSE_PUBLIC_KEY") || !getEnvVar("LANGFUSE_SECRET_KEY")) {
      logger.debug(
        "Langfuse API keys not found - tracing disabled. Set LANGFUSE_PUBLIC_KEY and LANGFUSE_SECRET_KEY to enable"
      );
    } else {
      langfuseState.initPromise = initializeLangfuse();
    }
    langfuseHandler = /* @__PURE__ */ __name(() => langfuseState.handler, "langfuseHandler");
    langfuseClient = /* @__PURE__ */ __name(() => langfuseState.client, "langfuseClient");
    langfuseInitPromise = /* @__PURE__ */ __name(() => langfuseState.initPromise, "langfuseInitPromise");
  }
});

// src/telemetry/events.ts
function createServerRunEventData(server, transport) {
  const toolRegistrations = Array.from(server.registrations.tools.values());
  const promptRegistrations = Array.from(server.registrations.prompts.values());
  const resourceRegistrations = Array.from(
    server.registrations.resources.values()
  );
  const templateRegistrations = Array.from(
    server.registrations.resourceTemplates.values()
  );
  const allResources = resourceRegistrations.map((r) => ({
    name: r.config.name,
    title: r.config.title ?? null,
    description: r.config.description ?? null,
    uri: r.config.uri ?? null,
    mime_type: r.config.mimeType ?? null
  }));
  const appsSdkResources = allResources.filter(
    (r) => r.mime_type === "text/html+skybridge"
  );
  const mcpUiResources = allResources.filter(
    (r) => r.mime_type === "text/uri-list" || r.mime_type === "text/html"
  );
  const mcpAppsResources = allResources.filter(
    (r) => r.mime_type === "text/html+mcp"
  );
  return {
    transport,
    toolsNumber: server.registeredTools.length,
    resourcesNumber: server.registeredResources.length,
    promptsNumber: server.registeredPrompts.length,
    auth: !!server.oauthProvider,
    name: server.config.name,
    description: server.config.description ?? null,
    baseUrl: server.serverBaseUrl ?? null,
    toolNames: server.registeredTools.length > 0 ? server.registeredTools : null,
    resourceNames: server.registeredResources.length > 0 ? server.registeredResources : null,
    promptNames: server.registeredPrompts.length > 0 ? server.registeredPrompts : null,
    tools: toolRegistrations.length > 0 ? toolRegistrations.map((r) => ({
      name: r.config.name,
      title: r.config.title ?? null,
      description: r.config.description ?? null,
      input_schema: r.config.schema ? JSON.stringify(r.config.schema) : null,
      output_schema: r.config.outputSchema ? JSON.stringify(r.config.outputSchema) : null
    })) : null,
    resources: allResources.length > 0 ? allResources : null,
    prompts: promptRegistrations.length > 0 ? promptRegistrations.map((r) => ({
      name: r.config.name,
      title: r.config.title ?? null,
      description: r.config.description ?? null,
      args: r.config.args ? JSON.stringify(r.config.args) : null
    })) : null,
    templates: templateRegistrations.length > 0 ? templateRegistrations.map((r) => ({
      name: r.config.name,
      title: r.config.title ?? null,
      description: r.config.description ?? null
    })) : null,
    capabilities: {
      logging: true,
      resources: { subscribe: true, listChanged: true }
    },
    appsSdkResources: appsSdkResources.length > 0 ? appsSdkResources : null,
    appsSdkResourcesNumber: appsSdkResources.length,
    mcpUiResources: mcpUiResources.length > 0 ? mcpUiResources : null,
    mcpUiResourcesNumber: mcpUiResources.length,
    mcpAppsResources: mcpAppsResources.length > 0 ? mcpAppsResources : null,
    mcpAppsResourcesNumber: mcpAppsResources.length
  };
}
var BaseTelemetryEvent, MCPAgentExecutionEvent, ServerRunEvent, ServerInitializeEvent, ServerToolCallEvent, ServerResourceCallEvent, ServerPromptCallEvent, ServerContextEvent, MCPClientInitEvent, ConnectorInitEvent, ClientAddServerEvent, ClientRemoveServerEvent;
var init_events = __esm({
  "src/telemetry/events.ts"() {
    "use strict";
    BaseTelemetryEvent = class {
      static {
        __name(this, "BaseTelemetryEvent");
      }
    };
    MCPAgentExecutionEvent = class extends BaseTelemetryEvent {
      constructor(data) {
        super();
        this.data = data;
      }
      static {
        __name(this, "MCPAgentExecutionEvent");
      }
      get name() {
        return "mcp_agent_execution";
      }
      get properties() {
        return {
          // Core execution info
          execution_method: this.data.executionMethod,
          query: this.data.query,
          query_length: this.data.query.length,
          success: this.data.success,
          // Agent configuration
          model_provider: this.data.modelProvider,
          model_name: this.data.modelName,
          server_count: this.data.serverCount,
          server_identifiers: this.data.serverIdentifiers,
          total_tools_available: this.data.totalToolsAvailable,
          tools_available_names: this.data.toolsAvailableNames,
          max_steps_configured: this.data.maxStepsConfigured,
          memory_enabled: this.data.memoryEnabled,
          use_server_manager: this.data.useServerManager,
          // Execution parameters (always include, even if null)
          max_steps_used: this.data.maxStepsUsed,
          manage_connector: this.data.manageConnector,
          external_history_used: this.data.externalHistoryUsed,
          // Execution results (always include, even if null)
          steps_taken: this.data.stepsTaken ?? null,
          tools_used_count: this.data.toolsUsedCount ?? null,
          tools_used_names: this.data.toolsUsedNames ?? null,
          response: this.data.response ?? null,
          response_length: this.data.response ? this.data.response.length : null,
          execution_time_ms: this.data.executionTimeMs ?? null,
          error_type: this.data.errorType ?? null,
          conversation_history_length: this.data.conversationHistoryLength ?? null
        };
      }
    };
    __name(createServerRunEventData, "createServerRunEventData");
    ServerRunEvent = class extends BaseTelemetryEvent {
      constructor(data) {
        super();
        this.data = data;
      }
      static {
        __name(this, "ServerRunEvent");
      }
      get name() {
        return "server_run";
      }
      get properties() {
        return {
          transport: this.data.transport,
          tools_number: this.data.toolsNumber,
          resources_number: this.data.resourcesNumber,
          prompts_number: this.data.promptsNumber,
          auth: this.data.auth,
          name: this.data.name,
          description: this.data.description ?? null,
          base_url: this.data.baseUrl ?? null,
          tool_names: this.data.toolNames ?? null,
          resource_names: this.data.resourceNames ?? null,
          prompt_names: this.data.promptNames ?? null,
          tools: this.data.tools ?? null,
          resources: this.data.resources ?? null,
          prompts: this.data.prompts ?? null,
          templates: this.data.templates ?? null,
          capabilities: this.data.capabilities ? JSON.stringify(this.data.capabilities) : null,
          apps_sdk_resources: this.data.appsSdkResources ? JSON.stringify(this.data.appsSdkResources) : null,
          apps_sdk_resources_number: this.data.appsSdkResourcesNumber ?? 0,
          mcp_ui_resources: this.data.mcpUiResources ? JSON.stringify(this.data.mcpUiResources) : null,
          mcp_ui_resources_number: this.data.mcpUiResourcesNumber ?? 0,
          mcp_apps_resources: this.data.mcpAppsResources ? JSON.stringify(this.data.mcpAppsResources) : null,
          mcp_apps_resources_number: this.data.mcpAppsResourcesNumber ?? 0
        };
      }
    };
    ServerInitializeEvent = class extends BaseTelemetryEvent {
      constructor(data) {
        super();
        this.data = data;
      }
      static {
        __name(this, "ServerInitializeEvent");
      }
      get name() {
        return "server_initialize_call";
      }
      get properties() {
        return {
          protocol_version: this.data.protocolVersion,
          client_info: JSON.stringify(this.data.clientInfo),
          client_capabilities: JSON.stringify(this.data.clientCapabilities),
          session_id: this.data.sessionId ?? null
        };
      }
    };
    ServerToolCallEvent = class extends BaseTelemetryEvent {
      constructor(data) {
        super();
        this.data = data;
      }
      static {
        __name(this, "ServerToolCallEvent");
      }
      get name() {
        return "server_tool_call";
      }
      get properties() {
        return {
          tool_name: this.data.toolName,
          length_input_argument: this.data.lengthInputArgument,
          success: this.data.success,
          error_type: this.data.errorType ?? null,
          execution_time_ms: this.data.executionTimeMs ?? null
        };
      }
    };
    ServerResourceCallEvent = class extends BaseTelemetryEvent {
      constructor(data) {
        super();
        this.data = data;
      }
      static {
        __name(this, "ServerResourceCallEvent");
      }
      get name() {
        return "server_resource_call";
      }
      get properties() {
        return {
          name: this.data.name,
          description: this.data.description,
          contents: this.data.contents,
          success: this.data.success,
          error_type: this.data.errorType ?? null
        };
      }
    };
    ServerPromptCallEvent = class extends BaseTelemetryEvent {
      constructor(data) {
        super();
        this.data = data;
      }
      static {
        __name(this, "ServerPromptCallEvent");
      }
      get name() {
        return "server_prompt_call";
      }
      get properties() {
        return {
          name: this.data.name,
          description: this.data.description,
          success: this.data.success,
          error_type: this.data.errorType ?? null
        };
      }
    };
    ServerContextEvent = class extends BaseTelemetryEvent {
      constructor(data) {
        super();
        this.data = data;
      }
      static {
        __name(this, "ServerContextEvent");
      }
      get name() {
        return `server_context_${this.data.contextType}`;
      }
      get properties() {
        return {
          context_type: this.data.contextType,
          notification_type: this.data.notificationType ?? null
        };
      }
    };
    MCPClientInitEvent = class extends BaseTelemetryEvent {
      constructor(data) {
        super();
        this.data = data;
      }
      static {
        __name(this, "MCPClientInitEvent");
      }
      get name() {
        return "mcpclient_init";
      }
      get properties() {
        return {
          code_mode: this.data.codeMode,
          sandbox: this.data.sandbox,
          all_callbacks: this.data.allCallbacks,
          verify: this.data.verify,
          servers: this.data.servers,
          num_servers: this.data.numServers,
          is_browser: this.data.isBrowser
        };
      }
    };
    ConnectorInitEvent = class extends BaseTelemetryEvent {
      constructor(data) {
        super();
        this.data = data;
      }
      static {
        __name(this, "ConnectorInitEvent");
      }
      get name() {
        return "connector_init";
      }
      get properties() {
        return {
          connector_type: this.data.connectorType,
          server_command: this.data.serverCommand ?? null,
          server_args: this.data.serverArgs ?? null,
          server_url: this.data.serverUrl ?? null,
          public_identifier: this.data.publicIdentifier ?? null
        };
      }
    };
    ClientAddServerEvent = class extends BaseTelemetryEvent {
      constructor(data) {
        super();
        this.data = data;
      }
      static {
        __name(this, "ClientAddServerEvent");
      }
      get name() {
        return "client_add_server";
      }
      get properties() {
        const { serverName, serverConfig } = this.data;
        const url = serverConfig.url;
        return {
          server_name: serverName,
          server_url_domain: url ? this._extractHostname(url) : null,
          transport: serverConfig.transport ?? null,
          has_auth: !!(serverConfig.authToken || serverConfig.authProvider)
        };
      }
      _extractHostname(url) {
        try {
          return new URL(url).hostname;
        } catch {
          return null;
        }
      }
    };
    ClientRemoveServerEvent = class extends BaseTelemetryEvent {
      constructor(data) {
        super();
        this.data = data;
      }
      static {
        __name(this, "ClientRemoveServerEvent");
      }
      get name() {
        return "client_remove_server";
      }
      get properties() {
        return {
          server_name: this.data.serverName
        };
      }
    };
  }
});

// src/version.ts
function getPackageVersion() {
  return VERSION;
}
var VERSION;
var init_version = __esm({
  "src/version.ts"() {
    "use strict";
    VERSION = "1.12.1";
    __name(getPackageVersion, "getPackageVersion");
  }
});

// src/telemetry/utils.ts
function getModelProvider(llm) {
  return llm._llm_type || llm.constructor.name.toLowerCase();
}
function getModelName(llm) {
  if ("_identifyingParams" in llm) {
    const identifyingParams = llm._identifyingParams;
    if (typeof identifyingParams === "object" && identifyingParams !== null) {
      for (const key of [
        "model",
        "modelName",
        "model_name",
        "modelId",
        "model_id",
        "deploymentName",
        "deployment_name"
      ]) {
        if (key in identifyingParams) {
          return String(identifyingParams[key]);
        }
      }
    }
  }
  return llm.model || llm.modelName || llm.constructor.name;
}
function extractModelInfo(llm) {
  return [getModelProvider(llm), getModelName(llm)];
}
var init_utils = __esm({
  "src/telemetry/utils.ts"() {
    "use strict";
    init_version();
    __name(getModelProvider, "getModelProvider");
    __name(getModelName, "getModelName");
    __name(extractModelInfo, "extractModelInfo");
  }
});

// src/telemetry/telemetry-browser.ts
function generateUUID() {
  if (typeof globalThis !== "undefined" && globalThis.crypto && typeof globalThis.crypto.randomUUID === "function") {
    return globalThis.crypto.randomUUID();
  }
  if (typeof globalThis !== "undefined" && globalThis.crypto && typeof globalThis.crypto.getRandomValues === "function") {
    const array = new Uint8Array(16);
    globalThis.crypto.getRandomValues(array);
    const hex = Array.from(array, (v) => v.toString(16).padStart(2, "0")).join(
      ""
    );
    return `${hex.substring(0, 8)}-${hex.substring(8, 12)}-${hex.substring(12, 16)}-${hex.substring(16, 20)}-${hex.substring(20)}`;
  }
  return `${Date.now()}-${Math.random().toString(36).substring(2, 15)}-${Math.random().toString(36).substring(2, 15)}`;
}
function secureRandomString() {
  if (typeof window !== "undefined" && window.crypto && typeof window.crypto.getRandomValues === "function") {
    const array = new Uint8Array(8);
    window.crypto.getRandomValues(array);
    return Array.from(array, (v) => v.toString(16).padStart(2, "0")).join("");
  }
  if (typeof globalThis !== "undefined" && globalThis.crypto && typeof globalThis.crypto.getRandomValues === "function") {
    const array = new Uint8Array(8);
    globalThis.crypto.getRandomValues(array);
    return Array.from(array, (v) => v.toString(16).padStart(2, "0")).join("");
  }
  return Math.random().toString(36).substring(2, 15);
}
function detectRuntimeEnvironment() {
  try {
    if (typeof window !== "undefined" && typeof document !== "undefined") {
      return "browser";
    }
    return "unknown";
  } catch {
    return "unknown";
  }
}
function getStorageCapability(env) {
  if (env === "browser") {
    try {
      if (typeof localStorage !== "undefined") {
        localStorage.setItem("__mcp_use_test__", "1");
        localStorage.removeItem("__mcp_use_test__");
        return "localStorage";
      }
    } catch {
    }
  }
  return "session-only";
}
function getRuntimeEnvironment() {
  if (cachedEnvironment === null) {
    cachedEnvironment = detectRuntimeEnvironment();
  }
  return cachedEnvironment;
}
function setTelemetrySource(source) {
  Tel.getInstance().setSource(source);
}
var USER_ID_STORAGE_KEY, cachedEnvironment, Telemetry, Tel;
var init_telemetry_browser = __esm({
  "src/telemetry/telemetry-browser.ts"() {
    "use strict";
    init_logging();
    init_events();
    init_utils();
    __name(generateUUID, "generateUUID");
    __name(secureRandomString, "secureRandomString");
    USER_ID_STORAGE_KEY = "mcp_use_user_id";
    __name(detectRuntimeEnvironment, "detectRuntimeEnvironment");
    __name(getStorageCapability, "getStorageCapability");
    cachedEnvironment = null;
    __name(getRuntimeEnvironment, "getRuntimeEnvironment");
    Telemetry = class _Telemetry {
      static {
        __name(this, "Telemetry");
      }
      static instance = null;
      PROJECT_API_KEY = "phc_lyTtbYwvkdSbrcMQNPiKiiRWrrM1seyKIMjycSvItEI";
      HOST = "https://eu.i.posthog.com";
      UNKNOWN_USER_ID = "UNKNOWN_USER_ID";
      _currUserId = null;
      _posthogBrowserClient = null;
      _posthogLoading = null;
      _runtimeEnvironment;
      _storageCapability;
      _source;
      constructor() {
        this._runtimeEnvironment = getRuntimeEnvironment();
        this._storageCapability = getStorageCapability(this._runtimeEnvironment);
        this._source = this._getSourceFromLocalStorage() || this._runtimeEnvironment;
        const telemetryDisabled = this._checkTelemetryDisabled();
        const canSupportTelemetry = this._runtimeEnvironment !== "unknown";
        if (telemetryDisabled) {
          this._posthogBrowserClient = null;
          logger.debug("Telemetry disabled via localStorage");
        } else if (!canSupportTelemetry) {
          this._posthogBrowserClient = null;
          logger.debug(
            `Telemetry disabled - unknown environment: ${this._runtimeEnvironment}`
          );
        } else {
          logger.info(
            "Anonymized telemetry enabled. Set MCP_USE_ANONYMIZED_TELEMETRY=false in localStorage to disable."
          );
          this._posthogLoading = this._initPostHogBrowser();
        }
      }
      _getSourceFromLocalStorage() {
        try {
          if (typeof localStorage !== "undefined") {
            return localStorage.getItem("MCP_USE_TELEMETRY_SOURCE");
          }
        } catch {
        }
        return null;
      }
      _checkTelemetryDisabled() {
        if (typeof localStorage !== "undefined" && localStorage.getItem("MCP_USE_ANONYMIZED_TELEMETRY") === "false") {
          return true;
        }
        return false;
      }
      async _initPostHogBrowser() {
        try {
          const posthogModule = await import("posthog-js");
          const posthogModuleTyped = posthogModule;
          const posthog = posthogModuleTyped.default || posthogModuleTyped.posthog;
          if (!posthog || typeof posthog.init !== "function") {
            throw new Error("posthog-js module did not export expected interface");
          }
          posthog.init(this.PROJECT_API_KEY, {
            api_host: this.HOST,
            persistence: "localStorage",
            autocapture: false,
            // We only want explicit captures
            capture_pageview: false,
            // We don't want automatic pageview tracking
            disable_session_recording: true,
            // No session recording
            loaded: /* @__PURE__ */ __name(() => {
              logger.debug("PostHog browser client initialized");
            }, "loaded")
          });
          this._posthogBrowserClient = posthog;
        } catch (e) {
          logger.warn(`Failed to initialize PostHog browser telemetry: ${e}`);
          this._posthogBrowserClient = null;
        }
      }
      /**
       * Get the detected runtime environment
       */
      get runtimeEnvironment() {
        return this._runtimeEnvironment;
      }
      /**
       * Get the storage capability for this environment
       */
      get storageCapability() {
        return this._storageCapability;
      }
      static getInstance() {
        if (!_Telemetry.instance) {
          _Telemetry.instance = new _Telemetry();
        }
        return _Telemetry.instance;
      }
      /**
       * Set the source identifier for telemetry events.
       * This allows tracking usage from different applications.
       * @param source - The source identifier (e.g., "my-app", "cli", "vs-code-extension")
       */
      setSource(source) {
        this._source = source;
        try {
          if (typeof localStorage !== "undefined") {
            localStorage.setItem("MCP_USE_TELEMETRY_SOURCE", source);
          }
        } catch {
        }
        logger.debug(`Telemetry source set to: ${source}`);
      }
      /**
       * Get the current source identifier.
       */
      getSource() {
        return this._source;
      }
      /**
       * Check if telemetry is enabled.
       */
      get isEnabled() {
        return this._posthogBrowserClient !== null;
      }
      get userId() {
        if (this._currUserId) {
          return this._currUserId;
        }
        try {
          switch (this._storageCapability) {
            case "localStorage":
              this._currUserId = this._getUserIdFromLocalStorage();
              break;
            case "session-only":
            default:
              try {
                this._currUserId = `session-${generateUUID()}`;
              } catch (uuidError) {
                this._currUserId = `session-${Date.now()}-${secureRandomString()}`;
              }
              break;
          }
        } catch (e) {
          this._currUserId = this.UNKNOWN_USER_ID;
        }
        return this._currUserId;
      }
      /**
       * Get or create user ID from localStorage (Browser)
       */
      _getUserIdFromLocalStorage() {
        try {
          if (typeof localStorage === "undefined") {
            throw new Error("localStorage is not available");
          }
          try {
            localStorage.setItem("__mcp_use_test__", "1");
            localStorage.removeItem("__mcp_use_test__");
          } catch (testError) {
            throw new Error(`localStorage is not writable: ${testError}`);
          }
          let userId = localStorage.getItem(USER_ID_STORAGE_KEY);
          if (!userId) {
            try {
              userId = generateUUID();
            } catch (uuidError) {
              userId = `${Date.now()}-${secureRandomString()}`;
            }
            localStorage.setItem(USER_ID_STORAGE_KEY, userId);
          }
          return userId;
        } catch (e) {
          logger.debug(`Failed to access localStorage for user ID: ${e}`);
          let sessionId;
          try {
            sessionId = `session-${generateUUID()}`;
          } catch (uuidError) {
            sessionId = `session-${Date.now()}-${secureRandomString()}`;
          }
          return sessionId;
        }
      }
      async capture(event) {
        if (this._posthogLoading) {
          await this._posthogLoading;
        }
        if (!this._posthogBrowserClient) {
          return;
        }
        const currentUserId = this.userId;
        const properties = { ...event.properties };
        properties.mcp_use_version = getPackageVersion();
        properties.language = "typescript";
        properties.source = this._source;
        properties.runtime = this._runtimeEnvironment;
        if (this._posthogBrowserClient) {
          try {
            this._posthogBrowserClient.capture(event.name, {
              ...properties,
              distinct_id: currentUserId
            });
          } catch (e) {
            logger.debug(
              `Failed to track PostHog Browser event ${event.name}: ${e}`
            );
          }
        }
      }
      // ============================================================================
      // Agent Events
      // ============================================================================
      async trackAgentExecution(data) {
        if (!this.isEnabled) return;
        const event = new MCPAgentExecutionEvent(data);
        await this.capture(event);
      }
      // ============================================================================
      // Server Events
      // ============================================================================
      /**
       * Track server run event directly from an MCPServer instance.
       */
      async trackServerRunFromServer(server, transport) {
        if (!this.isEnabled) return;
        const data = createServerRunEventData(server, transport);
        const event = new ServerRunEvent(data);
        await this.capture(event);
      }
      async trackServerInitialize(data) {
        if (!this.isEnabled) return;
        const event = new ServerInitializeEvent(data);
        await this.capture(event);
      }
      async trackServerToolCall(data) {
        if (!this.isEnabled) return;
        const event = new ServerToolCallEvent(data);
        await this.capture(event);
      }
      async trackServerResourceCall(data) {
        if (!this.isEnabled) return;
        const event = new ServerResourceCallEvent(data);
        await this.capture(event);
      }
      async trackServerPromptCall(data) {
        if (!this.isEnabled) return;
        const event = new ServerPromptCallEvent(data);
        await this.capture(event);
      }
      async trackServerContext(data) {
        if (!this.isEnabled) return;
        const event = new ServerContextEvent(data);
        await this.capture(event);
      }
      // ============================================================================
      // Client Events
      // ============================================================================
      async trackMCPClientInit(data) {
        if (!this.isEnabled) return;
        const event = new MCPClientInitEvent(data);
        await this.capture(event);
      }
      async trackConnectorInit(data) {
        if (!this.isEnabled) return;
        const event = new ConnectorInitEvent(data);
        await this.capture(event);
      }
      async trackClientAddServer(serverName, serverConfig) {
        if (!this.isEnabled) return;
        const event = new ClientAddServerEvent({ serverName, serverConfig });
        await this.capture(event);
      }
      async trackClientRemoveServer(serverName) {
        if (!this.isEnabled) return;
        const event = new ClientRemoveServerEvent({ serverName });
        await this.capture(event);
      }
      // ============================================================================
      // React Hook / Browser specific events
      // ============================================================================
      async trackUseMcpConnection(data) {
        if (!this.isEnabled) return;
        await this.capture({
          name: "usemcp_connection",
          properties: {
            url_domain: new URL(data.url).hostname,
            // Only domain for privacy
            transport_type: data.transportType,
            success: data.success,
            error_type: data.errorType ?? null,
            connection_time_ms: data.connectionTimeMs ?? null,
            has_oauth: data.hasOAuth,
            has_sampling: data.hasSampling,
            has_elicitation: data.hasElicitation
          }
        });
      }
      async trackUseMcpToolCall(data) {
        if (!this.isEnabled) return;
        await this.capture({
          name: "usemcp_tool_call",
          properties: {
            tool_name: data.toolName,
            success: data.success,
            error_type: data.errorType ?? null,
            execution_time_ms: data.executionTimeMs ?? null
          }
        });
      }
      async trackUseMcpResourceRead(data) {
        if (!this.isEnabled) return;
        await this.capture({
          name: "usemcp_resource_read",
          properties: {
            resource_uri_scheme: data.resourceUri.split(":")[0],
            // Only scheme for privacy
            success: data.success,
            error_type: data.errorType ?? null
          }
        });
      }
      // ============================================================================
      // Browser-specific Methods
      // ============================================================================
      /**
       * Identify the current user (useful for linking sessions)
       * Browser only
       */
      identify(userId, properties) {
        if (this._posthogBrowserClient) {
          try {
            this._posthogBrowserClient.identify(userId, properties);
          } catch (e) {
            logger.debug(`Failed to identify user: ${e}`);
          }
        }
      }
      /**
       * Reset the user identity (useful for logout)
       * Browser only
       */
      reset() {
        if (this._posthogBrowserClient) {
          try {
            this._posthogBrowserClient.reset();
          } catch (e) {
            logger.debug(`Failed to reset user: ${e}`);
          }
        }
        this._currUserId = null;
      }
      // ============================================================================
      // Node.js-specific Methods (no-ops in browser)
      // ============================================================================
      /**
       * Flush the telemetry queue (Node.js only - no-op in browser)
       */
      flush() {
      }
      /**
       * Shutdown the telemetry client (Node.js only - no-op in browser)
       */
      shutdown() {
      }
      /**
       * Track package download event (Node.js only - no-op in browser)
       */
      async trackPackageDownload(properties) {
      }
    };
    Tel = Telemetry;
    __name(setTelemetrySource, "setTelemetrySource");
  }
});

// src/telemetry/index.ts
var init_telemetry = __esm({
  "src/telemetry/index.ts"() {
    "use strict";
    init_events();
    init_utils();
    init_telemetry_browser();
  }
});

// src/session.ts
var MCPSession;
var init_session = __esm({
  "src/session.ts"() {
    "use strict";
    MCPSession = class {
      static {
        __name(this, "MCPSession");
      }
      connector;
      autoConnect;
      constructor(connector, autoConnect = true) {
        this.connector = connector;
        this.autoConnect = autoConnect;
      }
      async connect() {
        await this.connector.connect();
      }
      async disconnect() {
        await this.connector.disconnect();
      }
      async initialize() {
        if (!this.isConnected && this.autoConnect) {
          await this.connect();
        }
        await this.connector.initialize();
      }
      get isConnected() {
        return this.connector && this.connector.isClientConnected;
      }
      /**
       * Register an event handler for session events
       *
       * @param event - The event type to listen for
       * @param handler - The handler function to call when the event occurs
       *
       * @example
       * ```typescript
       * session.on("notification", async (notification) => {
       *   console.log(`Received: ${notification.method}`, notification.params);
       *
       *   if (notification.method === "notifications/tools/list_changed") {
       *     // Refresh tools list
       *   }
       * });
       * ```
       */
      on(event, handler) {
        if (event === "notification") {
          this.connector.onNotification(handler);
        }
      }
      /**
       * Set roots and notify the server.
       * Roots represent directories or files that the client has access to.
       *
       * @param roots - Array of Root objects with `uri` (must start with "file://") and optional `name`
       *
       * @example
       * ```typescript
       * await session.setRoots([
       *   { uri: "file:///home/user/project", name: "My Project" },
       *   { uri: "file:///home/user/data" }
       * ]);
       * ```
       */
      async setRoots(roots) {
        return this.connector.setRoots(roots);
      }
      /**
       * Get the current roots.
       */
      getRoots() {
        return this.connector.getRoots();
      }
      /**
       * Get the cached list of tools from the server.
       *
       * @returns Array of available tools
       *
       * @example
       * ```typescript
       * const tools = session.tools;
       * console.log(`Available tools: ${tools.map(t => t.name).join(", ")}`);
       * ```
       */
      get tools() {
        return this.connector.tools;
      }
      /**
       * List all available tools from the MCP server.
       * This method fetches fresh tools from the server, unlike the `tools` getter which returns cached tools.
       *
       * @param options - Optional request options
       * @returns Array of available tools
       *
       * @example
       * ```typescript
       * const tools = await session.listTools();
       * console.log(`Available tools: ${tools.map(t => t.name).join(", ")}`);
       * ```
       */
      async listTools(options) {
        return this.connector.listTools(options);
      }
      /**
       * Get the server capabilities advertised during initialization.
       *
       * @returns Server capabilities object
       */
      get serverCapabilities() {
        return this.connector.serverCapabilities;
      }
      /**
       * Get the server information (name and version).
       *
       * @returns Server info object or null if not available
       */
      get serverInfo() {
        return this.connector.serverInfo;
      }
      /**
       * Call a tool on the server.
       *
       * @param name - Name of the tool to call
       * @param args - Arguments to pass to the tool (defaults to empty object)
       * @param options - Optional request options (timeout, progress handlers, etc.)
       * @returns Result from the tool execution
       *
       * @example
       * ```typescript
       * const result = await session.callTool("add", { a: 5, b: 3 });
       * console.log(`Result: ${result.content[0].text}`);
       * ```
       */
      async callTool(name, args = {}, options) {
        return this.connector.callTool(name, args, options);
      }
      /**
       * List resources from the server with optional pagination.
       *
       * @param cursor - Optional cursor for pagination
       * @param options - Request options
       * @returns Resource list with optional nextCursor for pagination
       *
       * @example
       * ```typescript
       * const result = await session.listResources();
       * console.log(`Found ${result.resources.length} resources`);
       * ```
       */
      async listResources(cursor, options) {
        return this.connector.listResources(cursor, options);
      }
      /**
       * List all resources from the server, automatically handling pagination.
       *
       * @param options - Request options
       * @returns Complete list of all resources
       *
       * @example
       * ```typescript
       * const result = await session.listAllResources();
       * console.log(`Total resources: ${result.resources.length}`);
       * ```
       */
      async listAllResources(options) {
        return this.connector.listAllResources(options);
      }
      /**
       * List resource templates from the server.
       *
       * @param options - Request options
       * @returns List of available resource templates
       *
       * @example
       * ```typescript
       * const result = await session.listResourceTemplates();
       * console.log(`Available templates: ${result.resourceTemplates.length}`);
       * ```
       */
      async listResourceTemplates(options) {
        return this.connector.listResourceTemplates(options);
      }
      /**
       * Read a resource by URI.
       *
       * @param uri - URI of the resource to read
       * @param options - Request options
       * @returns Resource content
       *
       * @example
       * ```typescript
       * const resource = await session.readResource("file:///path/to/file.txt");
       * console.log(resource.contents);
       * ```
       */
      async readResource(uri, options) {
        return this.connector.readResource(uri, options);
      }
      /**
       * Subscribe to resource updates.
       *
       * @param uri - URI of the resource to subscribe to
       * @param options - Request options
       *
       * @example
       * ```typescript
       * await session.subscribeToResource("file:///path/to/file.txt");
       * // Now you'll receive notifications when this resource changes
       * ```
       */
      async subscribeToResource(uri, options) {
        return this.connector.subscribeToResource(uri, options);
      }
      /**
       * Unsubscribe from resource updates.
       *
       * @param uri - URI of the resource to unsubscribe from
       * @param options - Request options
       *
       * @example
       * ```typescript
       * await session.unsubscribeFromResource("file:///path/to/file.txt");
       * ```
       */
      async unsubscribeFromResource(uri, options) {
        return this.connector.unsubscribeFromResource(uri, options);
      }
      /**
       * List available prompts from the server.
       *
       * @returns List of available prompts
       *
       * @example
       * ```typescript
       * const result = await session.listPrompts();
       * console.log(`Available prompts: ${result.prompts.length}`);
       * ```
       */
      async listPrompts() {
        return this.connector.listPrompts();
      }
      /**
       * Get a specific prompt with arguments.
       *
       * @param name - Name of the prompt to get
       * @param args - Arguments for the prompt
       * @returns Prompt result
       *
       * @example
       * ```typescript
       * const prompt = await session.getPrompt("greeting", { name: "Alice" });
       * console.log(prompt.messages);
       * ```
       */
      async getPrompt(name, args) {
        return this.connector.getPrompt(name, args);
      }
      /**
       * Send a raw request through the client.
       *
       * @param method - MCP method name
       * @param params - Request parameters
       * @param options - Request options
       * @returns Response from the server
       *
       * @example
       * ```typescript
       * const result = await session.request("custom/method", { key: "value" });
       * ```
       */
      async request(method, params = null, options) {
        return this.connector.request(method, params, options);
      }
    };
  }
});

// src/client/base.ts
var BaseMCPClient;
var init_base = __esm({
  "src/client/base.ts"() {
    "use strict";
    init_logging();
    init_session();
    init_telemetry();
    BaseMCPClient = class {
      static {
        __name(this, "BaseMCPClient");
      }
      config = {};
      sessions = {};
      activeSessions = [];
      constructor(config) {
        if (config) {
          this.config = config;
        }
      }
      static fromDict(_cfg) {
        throw new Error("fromDict must be implemented by concrete class");
      }
      addServer(name, serverConfig) {
        this.config.mcpServers = this.config.mcpServers || {};
        this.config.mcpServers[name] = serverConfig;
        Tel.getInstance().trackClientAddServer(name, serverConfig);
      }
      removeServer(name) {
        if (this.config.mcpServers?.[name]) {
          delete this.config.mcpServers[name];
          this.activeSessions = this.activeSessions.filter((n) => n !== name);
          Tel.getInstance().trackClientRemoveServer(name);
        }
      }
      getServerNames() {
        return Object.keys(this.config.mcpServers ?? {});
      }
      getServerConfig(name) {
        return this.config.mcpServers?.[name];
      }
      getConfig() {
        return this.config ?? {};
      }
      async createSession(serverName, autoInitialize = true) {
        const servers = this.config.mcpServers ?? {};
        if (Object.keys(servers).length === 0) {
          logger.warn("No MCP servers defined in config");
        }
        if (!servers[serverName]) {
          throw new Error(`Server '${serverName}' not found in config`);
        }
        const connector = this.createConnectorFromConfig(servers[serverName]);
        const session = new MCPSession(connector);
        if (autoInitialize) {
          await session.initialize();
        }
        this.sessions[serverName] = session;
        if (!this.activeSessions.includes(serverName)) {
          this.activeSessions.push(serverName);
        }
        return session;
      }
      async createAllSessions(autoInitialize = true) {
        const servers = this.config.mcpServers ?? {};
        if (Object.keys(servers).length === 0) {
          logger.warn("No MCP servers defined in config");
        }
        for (const name of Object.keys(servers)) {
          await this.createSession(name, autoInitialize);
        }
        return this.sessions;
      }
      getSession(serverName) {
        const session = this.sessions[serverName];
        if (!session) {
          return null;
        }
        return session;
      }
      requireSession(serverName) {
        const session = this.sessions[serverName];
        if (!session) {
          throw new Error(
            `Session '${serverName}' not found. Available sessions: ${this.activeSessions.join(", ") || "none"}`
          );
        }
        return session;
      }
      getAllActiveSessions() {
        return Object.fromEntries(
          this.activeSessions.map((n) => [n, this.sessions[n]])
        );
      }
      async closeSession(serverName) {
        const session = this.sessions[serverName];
        if (!session) {
          logger.warn(
            `No session exists for server ${serverName}, nothing to close`
          );
          return;
        }
        try {
          logger.debug(`Closing session for server ${serverName}`);
          await session.disconnect();
        } catch (e) {
          logger.error(`Error closing session for server '${serverName}': ${e}`);
        } finally {
          delete this.sessions[serverName];
          this.activeSessions = this.activeSessions.filter((n) => n !== serverName);
        }
      }
      async closeAllSessions() {
        const serverNames = Object.keys(this.sessions);
        const errors = [];
        for (const serverName of serverNames) {
          try {
            logger.debug(`Closing session for server ${serverName}`);
            await this.closeSession(serverName);
          } catch (e) {
            const errorMsg = `Failed to close session for server '${serverName}': ${e}`;
            logger.error(errorMsg);
            errors.push(errorMsg);
          }
        }
        if (errors.length) {
          logger.error(
            `Encountered ${errors.length} errors while closing sessions`
          );
        } else {
          logger.debug("All sessions closed successfully");
        }
      }
    };
  }
});

// src/client/executors/base.ts
var BaseCodeExecutor;
var init_base2 = __esm({
  "src/client/executors/base.ts"() {
    "use strict";
    init_logging();
    BaseCodeExecutor = class {
      static {
        __name(this, "BaseCodeExecutor");
      }
      client;
      _connecting = false;
      constructor(client) {
        this.client = client;
      }
      /**
       * Ensure all configured MCP servers are connected before execution.
       * Prevents race conditions with a connection lock.
       */
      async ensureServersConnected() {
        const configuredServers = this.client.getServerNames();
        const activeSessions = Object.keys(this.client.getAllActiveSessions());
        const missingServers = configuredServers.filter(
          (s) => !activeSessions.includes(s)
        );
        if (missingServers.length > 0 && !this._connecting) {
          this._connecting = true;
          try {
            logger.debug(
              `Connecting to configured servers for code execution: ${missingServers.join(", ")}`
            );
            await this.client.createAllSessions();
          } finally {
            this._connecting = false;
          }
        } else if (missingServers.length > 0 && this._connecting) {
          logger.debug("Waiting for ongoing server connection...");
          const startWait = Date.now();
          while (this._connecting && Date.now() - startWait < 5e3) {
            await new Promise((resolve) => setTimeout(resolve, 100));
          }
        }
      }
      /**
       * Get tool namespace information from all active MCP sessions.
       * Filters out the internal code_mode server.
       */
      getToolNamespaces() {
        const namespaces = [];
        const activeSessions = this.client.getAllActiveSessions();
        for (const [serverName, session] of Object.entries(activeSessions)) {
          if (serverName === "code_mode") continue;
          try {
            const connector = session.connector;
            let tools;
            try {
              tools = connector.tools;
            } catch (e) {
              logger.warn(`Tools not available for server ${serverName}: ${e}`);
              continue;
            }
            if (!tools || tools.length === 0) continue;
            namespaces.push({ serverName, tools, session });
          } catch (e) {
            logger.warn(`Failed to load tools for server ${serverName}: ${e}`);
          }
        }
        return namespaces;
      }
      /**
       * Create a search function for discovering available MCP tools.
       * Used by code execution environments to find tools at runtime.
       */
      createSearchToolsFunction() {
        return async (query = "", detailLevel = "full") => {
          const allTools = [];
          const allNamespaces = /* @__PURE__ */ new Set();
          const queryLower = query.toLowerCase();
          const activeSessions = this.client.getAllActiveSessions();
          for (const [serverName, session] of Object.entries(activeSessions)) {
            if (serverName === "code_mode") continue;
            try {
              const tools = session.connector.tools;
              if (tools && tools.length > 0) {
                allNamespaces.add(serverName);
              }
              for (const tool of tools) {
                if (detailLevel === "names") {
                  allTools.push({ name: tool.name, server: serverName });
                } else if (detailLevel === "descriptions") {
                  allTools.push({
                    name: tool.name,
                    server: serverName,
                    description: tool.description
                  });
                } else {
                  allTools.push({
                    name: tool.name,
                    server: serverName,
                    description: tool.description,
                    input_schema: tool.inputSchema
                  });
                }
              }
            } catch (e) {
              logger.warn(`Failed to search tools in server ${serverName}: ${e}`);
            }
          }
          let filteredTools = allTools;
          if (query) {
            filteredTools = allTools.filter((tool) => {
              const nameMatch = tool.name.toLowerCase().includes(queryLower);
              const descMatch = tool.description?.toLowerCase().includes(queryLower);
              const serverMatch = tool.server.toLowerCase().includes(queryLower);
              return nameMatch || descMatch || serverMatch;
            });
          }
          return {
            meta: {
              total_tools: allTools.length,
              namespaces: Array.from(allNamespaces).sort(),
              result_count: filteredTools.length
            },
            results: filteredTools
          };
        };
      }
    };
  }
});

// src/client/executors/e2b.ts
var E2BCodeExecutor;
var init_e2b = __esm({
  "src/client/executors/e2b.ts"() {
    "use strict";
    init_logging();
    init_base2();
    E2BCodeExecutor = class extends BaseCodeExecutor {
      static {
        __name(this, "E2BCodeExecutor");
      }
      e2bApiKey;
      codeExecSandbox = null;
      SandboxClass = null;
      timeoutMs;
      constructor(client, options) {
        super(client);
        this.e2bApiKey = options.apiKey;
        this.timeoutMs = options.timeoutMs ?? 3e5;
      }
      /**
       * Lazy load E2B Sandbox class.
       * This allows the library to work without E2B installed.
       */
      async ensureSandboxClass() {
        if (this.SandboxClass) return;
        try {
          const e2b = await import("@e2b/code-interpreter");
          this.SandboxClass = e2b.Sandbox;
        } catch (error) {
          throw new Error(
            "@e2b/code-interpreter is not installed. The E2B code executor requires this optional dependency. Install it with: yarn add @e2b/code-interpreter"
          );
        }
      }
      /**
       * Get or create a dedicated sandbox for code execution.
       */
      async getOrCreateCodeExecSandbox() {
        if (this.codeExecSandbox) return this.codeExecSandbox;
        await this.ensureSandboxClass();
        logger.debug("Starting E2B sandbox for code execution...");
        this.codeExecSandbox = await this.SandboxClass.create("base", {
          apiKey: this.e2bApiKey,
          timeoutMs: this.timeoutMs
        });
        return this.codeExecSandbox;
      }
      /**
       * Generate the shim code that exposes tools to the sandbox environment.
       * Creates a bridge that intercepts tool calls and sends them back to host.
       */
      generateShim(tools) {
        let shim = `
// MCP Bridge Shim
global.__callMcpTool = async (server, tool, args) => {
    const id = Math.random().toString(36).substring(7);
    console.log(JSON.stringify({
        type: '__MCP_TOOL_CALL__',
        id,
        server,
        tool,
        args
    }));
    
    const resultPath = \`/tmp/mcp_result_\${id}.json\`;
    const fs = require('fs');
    
    // Poll for result file
    let attempts = 0;
    while (attempts < 300) { // 30 seconds timeout
        if (fs.existsSync(resultPath)) {
            const content = fs.readFileSync(resultPath, 'utf8');
            const result = JSON.parse(content);
            fs.unlinkSync(resultPath); // Clean up
            
            if (result.error) {
                throw new Error(result.error);
            }
            return result.data;
        }
        await new Promise(resolve => setTimeout(resolve, 100));
        attempts++;
    }
    throw new Error('Tool execution timed out');
};

// Global search_tools helper
global.search_tools = async (query, detailLevel = 'full') => {
    const allTools = ${JSON.stringify(
          Object.entries(tools).flatMap(
            ([server, serverTools]) => serverTools.map((tool) => ({
              name: tool.name,
              description: tool.description,
              server,
              input_schema: tool.inputSchema
            }))
          )
        )};
    
    const filtered = allTools.filter(tool => {
        if (!query) return true;
        const q = query.toLowerCase();
        return tool.name.toLowerCase().includes(q) || 
               (tool.description && tool.description.toLowerCase().includes(q));
    });
    
    if (detailLevel === 'names') {
        return filtered.map(t => ({ name: t.name, server: t.server }));
    } else if (detailLevel === 'descriptions') {
        return filtered.map(t => ({ name: t.name, server: t.server, description: t.description }));
    }
    return filtered;
};
`;
        for (const [serverName, serverTools] of Object.entries(tools)) {
          if (!serverTools || serverTools.length === 0) continue;
          const safeServerName = serverName.replace(/[^a-zA-Z0-9_]/g, "_");
          shim += `
global['${serverName}'] = {`;
          for (const tool of serverTools) {
            shim += `
    '${tool.name}': async (args) => await global.__callMcpTool('${serverName}', '${tool.name}', args),`;
          }
          shim += `
};

// Also expose as safe name if different
if ('${safeServerName}' !== '${serverName}') {
    global['${safeServerName}'] = global['${serverName}'];
}
`;
        }
        return shim;
      }
      /**
       * Build the tool catalog for the shim.
       * Returns a map of server names to their available tools.
       */
      buildToolCatalog() {
        const catalog = {};
        const namespaces = this.getToolNamespaces();
        for (const { serverName, tools } of namespaces) {
          catalog[serverName] = tools;
        }
        return catalog;
      }
      /**
       * Execute JavaScript/TypeScript code in an E2B sandbox with MCP tool access.
       * Tool calls are proxied back to the host via the bridge pattern.
       *
       * @param code - Code to execute
       * @param timeout - Execution timeout in milliseconds (default: 30000)
       */
      async execute(code, timeout = 3e4) {
        const startTime = Date.now();
        let result = null;
        let error = null;
        let logs = [];
        try {
          await this.ensureServersConnected();
          const sandbox = await this.getOrCreateCodeExecSandbox();
          const toolCatalog = this.buildToolCatalog();
          const shim = this.generateShim(toolCatalog);
          const wrappedCode = `
${shim}

(async () => {
    try {
        const func = async () => {
            ${code}
        };
        const result = await func();
        console.log('__MCP_RESULT_START__');
        console.log(JSON.stringify(result));
        console.log('__MCP_RESULT_END__');
    } catch (e) {
        console.error(e);
        process.exit(1);
    }
})();
`;
          const filename = `exec_${Date.now()}.js`;
          await sandbox.files.write(filename, wrappedCode);
          const execution = await sandbox.commands.run(`node ${filename}`, {
            timeoutMs: timeout,
            onStdout: /* @__PURE__ */ __name(async (data) => {
              try {
                const lines = data.split("\n");
                for (const line of lines) {
                  if (line.trim().startsWith('{"type":"__MCP_TOOL_CALL__"')) {
                    const call = JSON.parse(line);
                    if (call.type === "__MCP_TOOL_CALL__") {
                      try {
                        logger.debug(
                          `[E2B Bridge] Calling tool ${call.server}.${call.tool}`
                        );
                        const activeSessions = this.client.getAllActiveSessions();
                        const session = activeSessions[call.server];
                        if (!session) {
                          throw new Error(`Server ${call.server} not found`);
                        }
                        const toolResult = await session.connector.callTool(
                          call.tool,
                          call.args
                        );
                        let extractedResult = toolResult;
                        if (toolResult.content && toolResult.content.length > 0) {
                          const item = toolResult.content[0];
                          if (item.type === "text") {
                            try {
                              extractedResult = JSON.parse(item.text);
                            } catch {
                              extractedResult = item.text;
                            }
                          } else {
                            extractedResult = item;
                          }
                        }
                        const resultPath = `/tmp/mcp_result_${call.id}.json`;
                        await sandbox.files.write(
                          resultPath,
                          JSON.stringify({ data: extractedResult })
                        );
                      } catch (err) {
                        logger.error(
                          `[E2B Bridge] Tool execution failed: ${err.message}`
                        );
                        const resultPath = `/tmp/mcp_result_${call.id}.json`;
                        await sandbox.files.write(
                          resultPath,
                          JSON.stringify({
                            error: err.message || String(err)
                          })
                        );
                      }
                    }
                  }
                }
              } catch (e) {
              }
            }, "onStdout")
          });
          logs = [execution.stdout, execution.stderr].filter(Boolean);
          if (execution.exitCode !== 0) {
            error = execution.stderr || "Execution failed";
          } else {
            const stdout = execution.stdout;
            const startMarker = "__MCP_RESULT_START__";
            const endMarker = "__MCP_RESULT_END__";
            const startIndex = stdout.indexOf(startMarker);
            const endIndex = stdout.indexOf(endMarker);
            if (startIndex !== -1 && endIndex !== -1) {
              const jsonStr = stdout.substring(startIndex + startMarker.length, endIndex).trim();
              try {
                result = JSON.parse(jsonStr);
              } catch (e) {
                result = jsonStr;
              }
              logs = logs.map((log) => {
                let cleaned = log.replace(
                  new RegExp(startMarker + "[\\s\\S]*?" + endMarker),
                  "[Result captured]"
                );
                cleaned = cleaned.split("\n").filter((l) => !l.includes("__MCP_TOOL_CALL__")).join("\n");
                return cleaned;
              });
            }
          }
        } catch (e) {
          error = e.message || String(e);
          if (error && (error.includes("timeout") || error.includes("timed out"))) {
            error = "Script execution timed out";
          }
        }
        return {
          result,
          logs,
          error,
          execution_time: (Date.now() - startTime) / 1e3
        };
      }
      /**
       * Clean up the E2B sandbox.
       * Should be called when the executor is no longer needed.
       */
      async cleanup() {
        if (this.codeExecSandbox) {
          try {
            await this.codeExecSandbox.kill();
            this.codeExecSandbox = null;
            logger.debug("E2B code execution sandbox stopped");
          } catch (error) {
            logger.error("Failed to stop E2B code execution sandbox:", error);
          }
        }
      }
    };
  }
});

// src/client/executors/vm.ts
function getVMModuleName() {
  return ["node", "vm"].join(":");
}
function tryLoadVM() {
  if (vmCheckAttempted) {
    return vm !== null;
  }
  vmCheckAttempted = true;
  try {
    const nodeRequire = typeof require !== "undefined" ? require : null;
    if (nodeRequire) {
      vm = nodeRequire(getVMModuleName());
      return true;
    }
  } catch (error) {
    logger.debug("node:vm module not available via require");
  }
  return false;
}
async function tryLoadVMAsync() {
  if (vm !== null) {
    return true;
  }
  if (!vmCheckAttempted) {
    if (tryLoadVM()) {
      return true;
    }
  }
  try {
    vm = await import(
      /* @vite-ignore */
      getVMModuleName()
    );
    return true;
  } catch (error) {
    logger.debug(
      "node:vm module not available in this environment (e.g., Deno)"
    );
    return false;
  }
}
function isVMAvailable() {
  tryLoadVM();
  return vm !== null;
}
var vm, vmCheckAttempted, VMCodeExecutor;
var init_vm = __esm({
  "src/client/executors/vm.ts"() {
    "use strict";
    init_logging();
    init_base2();
    vm = null;
    vmCheckAttempted = false;
    __name(getVMModuleName, "getVMModuleName");
    __name(tryLoadVM, "tryLoadVM");
    __name(tryLoadVMAsync, "tryLoadVMAsync");
    __name(isVMAvailable, "isVMAvailable");
    VMCodeExecutor = class extends BaseCodeExecutor {
      static {
        __name(this, "VMCodeExecutor");
      }
      defaultTimeout;
      memoryLimitMb;
      constructor(client, options) {
        super(client);
        this.defaultTimeout = options?.timeoutMs ?? 3e4;
        this.memoryLimitMb = options?.memoryLimitMb;
        tryLoadVM();
      }
      /**
       * Ensure VM module is loaded before execution
       */
      async ensureVMLoaded() {
        if (vm !== null) {
          return;
        }
        const loaded = await tryLoadVMAsync();
        if (!loaded) {
          throw new Error(
            "node:vm module is not available in this environment. Please use E2B executor instead or run in a Node.js environment."
          );
        }
      }
      /**
       * Execute JavaScript/TypeScript code with access to MCP tools.
       *
       * @param code - Code to execute
       * @param timeout - Execution timeout in milliseconds (default: configured timeout or 30000)
       */
      async execute(code, timeout) {
        const effectiveTimeout = timeout ?? this.defaultTimeout;
        await this.ensureVMLoaded();
        await this.ensureServersConnected();
        const logs = [];
        const startTime = Date.now();
        let result = null;
        let error = null;
        try {
          const context = await this._buildContext(logs);
          const wrappedCode = `
        (async () => {
          try {
            ${code}
          } catch (e) {
            throw e;
          }
        })()
      `;
          const script = new vm.Script(wrappedCode, {
            filename: "agent_code.js"
          });
          const promise = script.runInNewContext(context, {
            timeout: effectiveTimeout,
            displayErrors: true
          });
          result = await promise;
        } catch (e) {
          error = e.message || String(e);
          if (e.code === "ERR_SCRIPT_EXECUTION_TIMEOUT" || e.message === "Script execution timed out." || typeof error === "string" && (error.includes("timed out") || error.includes("timeout"))) {
            error = "Script execution timed out";
          }
          if (e.stack) {
            logger.debug(`Code execution error stack: ${e.stack}`);
          }
        }
        const executionTime = (Date.now() - startTime) / 1e3;
        return {
          result,
          logs,
          error,
          execution_time: executionTime
        };
      }
      /**
       * Build the VM execution context with MCP tools and standard globals.
       *
       * @param logs - Array to capture console output
       */
      async _buildContext(logs) {
        const logHandler = /* @__PURE__ */ __name((...args) => {
          logs.push(
            args.map(
              (arg) => typeof arg === "object" ? JSON.stringify(arg, null, 2) : String(arg)
            ).join(" ")
          );
        }, "logHandler");
        const sandbox = {
          console: {
            log: logHandler,
            error: /* @__PURE__ */ __name((...args) => {
              logHandler("[ERROR]", ...args);
            }, "error"),
            warn: /* @__PURE__ */ __name((...args) => {
              logHandler("[WARN]", ...args);
            }, "warn"),
            info: logHandler,
            debug: logHandler
          },
          // Standard globals
          Object,
          Array,
          String,
          Number,
          Boolean,
          Date,
          Math,
          JSON,
          RegExp,
          Map,
          Set,
          Promise,
          parseInt,
          parseFloat,
          isNaN,
          isFinite,
          encodeURI,
          decodeURI,
          encodeURIComponent,
          decodeURIComponent,
          setTimeout,
          clearTimeout,
          // Helper for tools
          search_tools: this.createSearchToolsFunction(),
          __tool_namespaces: []
        };
        const toolNamespaces = {};
        const namespaceInfos = this.getToolNamespaces();
        for (const { serverName, tools, session } of namespaceInfos) {
          const serverNamespace = {};
          for (const tool of tools) {
            const toolName = tool.name;
            serverNamespace[toolName] = async (args) => {
              const result = await session.connector.callTool(toolName, args || {});
              if (result.content && result.content.length > 0) {
                const item = result.content[0];
                if (item.type === "text") {
                  try {
                    return JSON.parse(item.text);
                  } catch {
                    return item.text;
                  }
                }
                return item;
              }
              return result;
            };
          }
          sandbox[serverName] = serverNamespace;
          toolNamespaces[serverName] = true;
        }
        sandbox.__tool_namespaces = Object.keys(toolNamespaces);
        return vm.createContext(sandbox);
      }
      /**
       * Clean up resources.
       * VM executor doesn't need cleanup, but method kept for interface consistency.
       */
      async cleanup() {
      }
    };
  }
});

// src/client/codeExecutor.ts
var init_codeExecutor = __esm({
  "src/client/codeExecutor.ts"() {
    "use strict";
    init_base2();
    init_e2b();
    init_vm();
    init_base2();
  }
});

// src/connectors/base.ts
var import_types, BaseConnector;
var init_base3 = __esm({
  "src/connectors/base.ts"() {
    "use strict";
    import_types = require("@modelcontextprotocol/sdk/types.js");
    init_logging();
    init_telemetry();
    BaseConnector = class {
      static {
        __name(this, "BaseConnector");
      }
      client = null;
      connectionManager = null;
      toolsCache = null;
      capabilitiesCache = null;
      serverInfoCache = null;
      connected = false;
      opts;
      notificationHandlers = [];
      rootsCache = [];
      constructor(opts = {}) {
        this.opts = opts;
        if (opts.roots) {
          this.rootsCache = [...opts.roots];
        }
      }
      /**
       * Track connector initialization event
       * Should be called by subclasses after successful connection
       */
      trackConnectorInit(data) {
        const connectorType = this.constructor.name;
        Telemetry.getInstance().trackConnectorInit({
          connectorType,
          ...data
        }).catch((e) => logger.debug(`Failed to track connector init: ${e}`));
      }
      /**
       * Register a handler for server notifications
       *
       * @param handler - Function to call when a notification is received
       *
       * @example
       * ```typescript
       * connector.onNotification((notification) => {
       *   console.log(`Received: ${notification.method}`, notification.params);
       * });
       * ```
       */
      onNotification(handler) {
        this.notificationHandlers.push(handler);
        if (this.client) {
          this.setupNotificationHandler();
        }
      }
      /**
       * Internal: wire notification handlers to the SDK client
       * Includes automatic handling for list_changed notifications per MCP spec
       */
      setupNotificationHandler() {
        if (!this.client) return;
        this.client.fallbackNotificationHandler = async (notification) => {
          switch (notification.method) {
            case "notifications/tools/list_changed":
              await this.refreshToolsCache();
              break;
            case "notifications/resources/list_changed":
              await this.onResourcesListChanged();
              break;
            case "notifications/prompts/list_changed":
              await this.onPromptsListChanged();
              break;
            default:
              break;
          }
          for (const handler of this.notificationHandlers) {
            try {
              await handler(notification);
            } catch (err) {
              logger.error("Error in notification handler:", err);
            }
          }
        };
      }
      /**
       * Auto-refresh tools cache when server sends tools/list_changed notification
       */
      async refreshToolsCache() {
        if (!this.client) return;
        try {
          logger.debug(
            "[Auto] Refreshing tools cache due to list_changed notification"
          );
          const result = await this.client.listTools();
          this.toolsCache = result.tools ?? [];
          logger.debug(
            `[Auto] Refreshed tools cache: ${this.toolsCache.length} tools`
          );
        } catch (err) {
          logger.warn("[Auto] Failed to refresh tools cache:", err);
        }
      }
      /**
       * Called when server sends resources/list_changed notification
       * Resources aren't cached by default, but we log for user awareness
       */
      async onResourcesListChanged() {
        logger.debug(
          "[Auto] Resources list changed - clients should re-fetch if needed"
        );
      }
      /**
       * Called when server sends prompts/list_changed notification
       * Prompts aren't cached by default, but we log for user awareness
       */
      async onPromptsListChanged() {
        logger.debug(
          "[Auto] Prompts list changed - clients should re-fetch if needed"
        );
      }
      /**
       * Set roots and notify the server.
       * Roots represent directories or files that the client has access to.
       *
       * @param roots - Array of Root objects with `uri` (must start with "file://") and optional `name`
       *
       * @example
       * ```typescript
       * await connector.setRoots([
       *   { uri: "file:///home/user/project", name: "My Project" },
       *   { uri: "file:///home/user/data" }
       * ]);
       * ```
       */
      async setRoots(roots) {
        this.rootsCache = [...roots];
        if (this.client) {
          logger.debug(
            `Sending roots/list_changed notification with ${roots.length} root(s)`
          );
          await this.client.sendRootsListChanged();
        }
      }
      /**
       * Get the current roots.
       */
      getRoots() {
        return [...this.rootsCache];
      }
      /**
       * Internal: set up roots/list request handler.
       * This is called after the client connects to register the handler for server requests.
       */
      setupRootsHandler() {
        if (!this.client) return;
        this.client.setRequestHandler(
          import_types.ListRootsRequestSchema,
          async (_request, _extra) => {
            logger.debug(
              `Server requested roots list, returning ${this.rootsCache.length} root(s)`
            );
            return { roots: this.rootsCache };
          }
        );
      }
      /**
       * Internal: set up sampling/createMessage request handler.
       * This is called after the client connects to register the handler for sampling requests.
       */
      setupSamplingHandler() {
        if (!this.client) {
          logger.debug("setupSamplingHandler: No client available");
          return;
        }
        if (!this.opts.samplingCallback) {
          logger.debug("setupSamplingHandler: No sampling callback provided");
          return;
        }
        logger.debug("setupSamplingHandler: Setting up sampling request handler");
        this.client.setRequestHandler(
          import_types.CreateMessageRequestSchema,
          async (request, _extra) => {
            logger.debug("Server requested sampling, forwarding to callback");
            return await this.opts.samplingCallback(request.params);
          }
        );
        logger.debug(
          "setupSamplingHandler: Sampling handler registered successfully"
        );
      }
      /**
       * Internal: set up elicitation/create request handler.
       * This is called after the client connects to register the handler for elicitation requests.
       */
      setupElicitationHandler() {
        if (!this.client) {
          logger.debug("setupElicitationHandler: No client available");
          return;
        }
        if (!this.opts.elicitationCallback) {
          logger.debug("setupElicitationHandler: No elicitation callback provided");
          return;
        }
        logger.debug(
          "setupElicitationHandler: Setting up elicitation request handler"
        );
        this.client.setRequestHandler(
          import_types.ElicitRequestSchema,
          async (request, _extra) => {
            logger.debug("Server requested elicitation, forwarding to callback");
            return await this.opts.elicitationCallback(request.params);
          }
        );
        logger.debug(
          "setupElicitationHandler: Elicitation handler registered successfully"
        );
      }
      /** Disconnect and release resources. */
      async disconnect() {
        if (!this.connected) {
          logger.debug("Not connected to MCP implementation");
          return;
        }
        logger.debug("Disconnecting from MCP implementation");
        await this.cleanupResources();
        this.connected = false;
        logger.debug("Disconnected from MCP implementation");
      }
      /** Check if the client is connected */
      get isClientConnected() {
        return this.client != null;
      }
      /**
       * Initialise the MCP session **after** `connect()` has succeeded.
       *
       * In the SDK, `Client.connect(transport)` automatically performs the
       * protocol‑level `initialize` handshake, so we only need to cache the list of
       * tools and expose some server info.
       */
      async initialize(defaultRequestOptions = this.opts.defaultRequestOptions ?? {}) {
        if (!this.client) {
          throw new Error("MCP client is not connected");
        }
        logger.debug("Caching server capabilities & tools");
        const capabilities = this.client.getServerCapabilities();
        this.capabilitiesCache = capabilities || null;
        const serverInfo = this.client.getServerVersion();
        this.serverInfoCache = serverInfo || null;
        const listToolsRes = await this.client.listTools(
          void 0,
          defaultRequestOptions
        );
        this.toolsCache = listToolsRes.tools ?? [];
        logger.debug(`Fetched ${this.toolsCache.length} tools from server`);
        logger.debug("Server capabilities:", capabilities);
        logger.debug("Server info:", serverInfo);
        return capabilities;
      }
      /** Lazily expose the cached tools list. */
      get tools() {
        if (!this.toolsCache) {
          throw new Error("MCP client is not initialized; call initialize() first");
        }
        return this.toolsCache;
      }
      /** Expose cached server capabilities. */
      get serverCapabilities() {
        return this.capabilitiesCache || {};
      }
      /** Expose cached server info. */
      get serverInfo() {
        return this.serverInfoCache;
      }
      /** Call a tool on the server. */
      async callTool(name, args, options) {
        if (!this.client) {
          throw new Error("MCP client is not connected");
        }
        const enhancedOptions = options ? { ...options } : void 0;
        if (enhancedOptions?.resetTimeoutOnProgress && !enhancedOptions.onprogress) {
          enhancedOptions.onprogress = () => {
          };
          logger.debug(
            `[BaseConnector] Added onprogress callback for tool '${name}' to enable progressToken`
          );
        }
        logger.debug(`Calling tool '${name}' with args`, args);
        const res = await this.client.callTool(
          { name, arguments: args },
          void 0,
          enhancedOptions
        );
        logger.debug(`Tool '${name}' returned`, res);
        return res;
      }
      /**
       * List all available tools from the MCP server.
       * This method fetches fresh tools from the server, unlike the `tools` getter which returns cached tools.
       *
       * @param options - Optional request options
       * @returns Array of available tools
       */
      async listTools(options) {
        if (!this.client) {
          throw new Error("MCP client is not connected");
        }
        const result = await this.client.listTools(void 0, options);
        return result.tools ?? [];
      }
      /**
       * List resources from the server with optional pagination
       *
       * @param cursor - Optional cursor for pagination
       * @param options - Request options
       * @returns Resource list with optional nextCursor for pagination
       */
      async listResources(cursor, options) {
        if (!this.client) {
          throw new Error("MCP client is not connected");
        }
        logger.debug("Listing resources", cursor ? `with cursor: ${cursor}` : "");
        return await this.client.listResources({ cursor }, options);
      }
      /**
       * List all resources from the server, automatically handling pagination
       *
       * @param options - Request options
       * @returns Complete list of all resources
       */
      async listAllResources(options) {
        if (!this.client) {
          throw new Error("MCP client is not connected");
        }
        if (!this.capabilitiesCache?.resources) {
          logger.debug("Server does not advertise resources capability, skipping");
          return { resources: [] };
        }
        try {
          logger.debug("Listing all resources (with auto-pagination)");
          const allResources = [];
          let cursor = void 0;
          do {
            const result = await this.client.listResources({ cursor }, options);
            allResources.push(...result.resources || []);
            cursor = result.nextCursor;
          } while (cursor);
          return { resources: allResources };
        } catch (err) {
          const error = err;
          if (error.code === -32601) {
            logger.debug("Server advertised resources but method not found");
            return { resources: [] };
          }
          throw err;
        }
      }
      /**
       * List resource templates from the server
       *
       * @param options - Request options
       * @returns List of available resource templates
       */
      async listResourceTemplates(options) {
        if (!this.client) {
          throw new Error("MCP client is not connected");
        }
        logger.debug("Listing resource templates");
        return await this.client.listResourceTemplates(void 0, options);
      }
      /** Read a resource by URI. */
      async readResource(uri, options) {
        if (!this.client) {
          throw new Error("MCP client is not connected");
        }
        logger.debug(`Reading resource ${uri}`);
        const res = await this.client.readResource({ uri }, options);
        return res;
      }
      /**
       * Subscribe to resource updates
       *
       * @param uri - URI of the resource to subscribe to
       * @param options - Request options
       */
      async subscribeToResource(uri, options) {
        if (!this.client) {
          throw new Error("MCP client is not connected");
        }
        logger.debug(`Subscribing to resource: ${uri}`);
        return await this.client.subscribeResource({ uri }, options);
      }
      /**
       * Unsubscribe from resource updates
       *
       * @param uri - URI of the resource to unsubscribe from
       * @param options - Request options
       */
      async unsubscribeFromResource(uri, options) {
        if (!this.client) {
          throw new Error("MCP client is not connected");
        }
        logger.debug(`Unsubscribing from resource: ${uri}`);
        return await this.client.unsubscribeResource({ uri }, options);
      }
      async listPrompts() {
        if (!this.client) {
          throw new Error("MCP client is not connected");
        }
        if (!this.capabilitiesCache?.prompts) {
          logger.debug("Server does not advertise prompts capability, skipping");
          return { prompts: [] };
        }
        try {
          logger.debug("Listing prompts");
          return await this.client.listPrompts();
        } catch (err) {
          const error = err;
          if (error.code === -32601) {
            logger.debug("Server advertised prompts but method not found");
            return { prompts: [] };
          }
          throw err;
        }
      }
      async getPrompt(name, args) {
        if (!this.client) {
          throw new Error("MCP client is not connected");
        }
        logger.debug(`Getting prompt ${name}`);
        return await this.client.getPrompt({ name, arguments: args });
      }
      /** Send a raw request through the client. */
      async request(method, params = null, options) {
        if (!this.client) {
          throw new Error("MCP client is not connected");
        }
        logger.debug(`Sending raw request '${method}' with params`, params);
        return await this.client.request(
          { method, params: params ?? {} },
          void 0,
          options
        );
      }
      /**
       * Helper to tear down the client & connection manager safely.
       */
      async cleanupResources() {
        const issues = [];
        if (this.client) {
          try {
            if (typeof this.client.close === "function") {
              await this.client.close();
            }
          } catch (e) {
            const msg = `Error closing client: ${e}`;
            logger.warn(msg);
            issues.push(msg);
          } finally {
            this.client = null;
          }
        }
        if (this.connectionManager) {
          try {
            await this.connectionManager.stop();
          } catch (e) {
            const msg = `Error stopping connection manager: ${e}`;
            logger.warn(msg);
            issues.push(msg);
          } finally {
            this.connectionManager = null;
          }
        }
        this.toolsCache = null;
        if (issues.length) {
          logger.warn(`Resource cleanup finished with ${issues.length} issue(s)`);
        }
      }
    };
  }
});

// src/client/connectors/codeMode.ts
var CODE_MODE_AGENT_PROMPT, CodeModeConnector;
var init_codeMode = __esm({
  "src/client/connectors/codeMode.ts"() {
    "use strict";
    init_base3();
    CODE_MODE_AGENT_PROMPT = `
## MCP Code Mode Tool Usage Guide

You have access to an MCP Code Mode Client that allows you to execute JavaScript/TypeScript code with access to registered tools. Follow this workflow:

### 1. Tool Discovery Phase
**Always start by discovering available tools:**
- Tools are organized by server namespace (e.g., \`server_name.tool_name\`)
- Use the \`search_tools(query, detail_level)\` function to find available tools
- You can access \`__tool_namespaces\` to see all available server namespaces

\`\`\`javascript
// Find all GitHub-related tools
const tools = await search_tools("github");
for (const tool of tools) {
    console.log(\`\${tool.server}.\${tool.name}: \${tool.description}\`);
}

// Get only tool names for quick overview
const tools = await search_tools("", "names");
\`\`\`

### 2. Interface Introspection
**Understand tool contracts before using them:**
- Use \`search_tools\` to get tool descriptions and input schemas
- Look for "Access as: server.tool(args)" patterns in descriptions

### 3. Code Execution Guidelines
**When writing code:**
- Use \`await server.tool({ param: value })\` syntax for all tool calls
- Tools are async functions that return promises
- You have access to standard JavaScript globals: \`console\`, \`JSON\`, \`Math\`, \`Date\`, etc.
- All console output (\`console.log\`, \`console.error\`, etc.) is automatically captured and returned
- Build properly structured input objects based on interface definitions
- Handle errors appropriately with try/catch blocks
- Chain tool calls by using results from previous calls

### 4. Best Practices
- **Discover first, code second**: Always explore available tools before writing execution code
- **Respect namespaces**: Use full \`server.tool\` names to avoid conflicts
- **Minimize Context**: Process large data in code, return only essential results
- **Error handling**: Wrap tool calls in try/catch for robustness
- **Data flow**: Chain tools by passing outputs as inputs to subsequent tools

### 5. Available Runtime Context
- \`search_tools(query, detail_level)\`: Function to discover tools
- \`__tool_namespaces\`: Array of available server namespaces
- All registered tools as \`server.tool\` functions
- Standard JavaScript built-ins for data processing

### Example Workflow

\`\`\`javascript
// 1. Discover available tools
const github_tools = await search_tools("github pull request");
console.log(\`Available GitHub PR tools: \${github_tools.map(t => t.name)}\`);

// 2. Call tools with proper parameters
const pr = await github.get_pull_request({
    owner: "facebook",
    repo: "react",
    number: 12345
});

// 3. Process results
let result;
if (pr.state === 'open' && pr.labels.some(l => l.name === 'bug')) {
    // 4. Chain with other tools
    await slack.post_message({
        channel: "#bugs",
        text: \`\u{1F41B} Bug PR needs review: \${pr.title}\`
    });
    result = "Notification sent";
} else {
    result = "No action needed";
}

// 5. Return structured results
return {
    pr_number: pr.number,
    pr_title: pr.title,
    action_taken: result
};
\`\`\`

Remember: Always discover and understand available tools before attempting to use them in code execution.
`;
    CodeModeConnector = class extends BaseConnector {
      static {
        __name(this, "CodeModeConnector");
      }
      mcpClient;
      _tools;
      constructor(client) {
        super();
        this.mcpClient = client;
        this.connected = true;
        this._tools = this._createToolsList();
      }
      async connect() {
        this.connected = true;
      }
      async disconnect() {
        this.connected = false;
      }
      get publicIdentifier() {
        return { name: "code_mode", version: "1.0.0" };
      }
      _createToolsList() {
        return [
          {
            name: "execute_code",
            description: "Execute JavaScript/TypeScript code with access to MCP tools. This is the PRIMARY way to interact with MCP servers in code mode. Write code that discovers tools using search_tools(), calls tools as async functions (e.g., await github.get_pull_request(...)), processes data efficiently, and returns results. Use 'await' for async operations and 'return' to return values. Available in code: search_tools(), __tool_namespaces, and server.tool_name() functions.",
            inputSchema: {
              type: "object",
              properties: {
                code: {
                  type: "string",
                  description: "JavaScript/TypeScript code to execute. Use 'await' for async operations. Use 'return' to return a value. Available: search_tools(), server.tool_name(), __tool_namespaces"
                },
                timeout: {
                  type: "number",
                  description: "Execution timeout in milliseconds",
                  default: 3e4
                }
              },
              required: ["code"]
            }
          },
          {
            name: "search_tools",
            description: "Search and discover available MCP tools across all servers. Use this to find out what tools are available before writing code. Returns tool information including names, descriptions, and schemas. Can filter by query and control detail level.",
            inputSchema: {
              type: "object",
              properties: {
                query: {
                  type: "string",
                  description: "Search query to filter tools by name or description",
                  default: ""
                },
                detail_level: {
                  type: "string",
                  description: "Detail level: 'names', 'descriptions', or 'full'",
                  enum: ["names", "descriptions", "full"],
                  default: "full"
                }
              }
            }
          }
        ];
      }
      // Override tools getter to return static list immediately
      get tools() {
        return this._tools;
      }
      async initialize() {
        this.toolsCache = this._tools;
        return { capabilities: {}, version: "1.0.0" };
      }
      async callTool(name, args) {
        if (name === "execute_code") {
          const code = args.code;
          const timeout = args.timeout || 3e4;
          const result = await this.mcpClient.executeCode(code, timeout);
          return {
            content: [
              {
                type: "text",
                text: JSON.stringify(result)
              }
            ]
          };
        } else if (name === "search_tools") {
          const query = args.query || "";
          const detailLevel = args.detail_level;
          const result = await this.mcpClient.searchTools(
            query,
            detailLevel && detailLevel in ["names", "descriptions", "full"] ? detailLevel : "full"
          );
          return {
            content: [
              {
                type: "text",
                text: JSON.stringify(result)
              }
            ]
          };
        }
        throw new Error(`Unknown tool: ${name}`);
      }
    };
  }
});

// src/task_managers/base.ts
var ConnectionManager;
var init_base4 = __esm({
  "src/task_managers/base.ts"() {
    "use strict";
    init_logging();
    ConnectionManager = class {
      static {
        __name(this, "ConnectionManager");
      }
      _readyPromise;
      _readyResolver;
      _donePromise;
      _doneResolver;
      _exception = null;
      _connection = null;
      _task = null;
      _abortController = null;
      constructor() {
        this.reset();
      }
      /**
       * Start the connection manager and establish a connection.
       *
       * @returns The established connection.
       * @throws If the connection cannot be established.
       */
      async start() {
        this.reset();
        logger.debug(`Starting ${this.constructor.name}`);
        this._task = this.connectionTask();
        await this._readyPromise;
        if (this._exception) {
          throw this._exception;
        }
        if (this._connection === null) {
          throw new Error("Connection was not established");
        }
        return this._connection;
      }
      /**
       * Stop the connection manager and close the connection.
       */
      async stop() {
        if (this._task && this._abortController) {
          logger.debug(`Cancelling ${this.constructor.name} task`);
          this._abortController.abort();
          try {
            await this._task;
          } catch (e) {
            if (e instanceof Error && e.name === "AbortError") {
              logger.debug(`${this.constructor.name} task aborted successfully`);
            } else {
              logger.warn(`Error stopping ${this.constructor.name} task: ${e}`);
            }
          }
        }
        await this._donePromise;
        logger.debug(`${this.constructor.name} task completed`);
      }
      /**
       * Reset all internal state.
       */
      reset() {
        this._readyPromise = new Promise((res) => this._readyResolver = res);
        this._donePromise = new Promise((res) => this._doneResolver = res);
        this._exception = null;
        this._connection = null;
        this._task = null;
        this._abortController = new AbortController();
      }
      /**
       * The background task responsible for establishing and maintaining the
       * connection until it is cancelled.
       */
      async connectionTask() {
        logger.debug(`Running ${this.constructor.name} task`);
        try {
          this._connection = await this.establishConnection();
          logger.debug(`${this.constructor.name} connected successfully`);
          this._readyResolver();
          await this.waitForAbort();
        } catch (err) {
          this._exception = err;
          logger.error(`Error in ${this.constructor.name} task: ${err}`);
          this._readyResolver();
        } finally {
          if (this._connection !== null) {
            try {
              await this.closeConnection(this._connection);
            } catch (closeErr) {
              logger.warn(
                `Error closing connection in ${this.constructor.name}: ${closeErr}`
              );
            }
            this._connection = null;
          }
          this._doneResolver();
        }
      }
      /**
       * Helper that returns a promise which resolves when the abort signal fires.
       */
      async waitForAbort() {
        return new Promise((_resolve, _reject) => {
          if (!this._abortController) {
            return;
          }
          const signal = this._abortController.signal;
          if (signal.aborted) {
            _resolve();
            return;
          }
          const onAbort = /* @__PURE__ */ __name(() => {
            signal.removeEventListener("abort", onAbort);
            _resolve();
          }, "onAbort");
          signal.addEventListener("abort", onAbort);
        });
      }
    };
  }
});

// src/task_managers/sse.ts
var import_sse, SseConnectionManager;
var init_sse = __esm({
  "src/task_managers/sse.ts"() {
    "use strict";
    import_sse = require("@modelcontextprotocol/sdk/client/sse.js");
    init_logging();
    init_base4();
    SseConnectionManager = class extends ConnectionManager {
      static {
        __name(this, "SseConnectionManager");
      }
      url;
      opts;
      _transport = null;
      reinitializing = false;
      /**
       * Create an SSE connection manager.
       *
       * @param url  The SSE endpoint URL.
       * @param opts Optional transport options (auth, headers, etc.).
       */
      constructor(url, opts) {
        super();
        this.url = typeof url === "string" ? new URL(url) : url;
        this.opts = opts;
      }
      /**
       * Spawn a new `SSEClientTransport` and wrap it with 404 handling.
       * Per MCP spec, clients MUST re-initialize when receiving 404 for stale sessions.
       */
      async establishConnection() {
        const transport = new import_sse.SSEClientTransport(this.url, this.opts);
        const originalSend = transport.send.bind(transport);
        transport.send = async (message) => {
          const sendMessage = /* @__PURE__ */ __name(async (msg) => {
            if (Array.isArray(msg)) {
              for (const singleMsg of msg) {
                await originalSend(singleMsg);
              }
            } else {
              await originalSend(msg);
            }
          }, "sendMessage");
          try {
            await sendMessage(message);
          } catch (error) {
            if (error?.code === 404 && transport.sessionId && !this.reinitializing) {
              logger.warn(
                `[SSE] Session not found (404), re-initializing per MCP spec...`
              );
              this.reinitializing = true;
              try {
                transport.sessionId = void 0;
                await this.reinitialize(transport);
                logger.info(`[SSE] Re-initialization successful, retrying request`);
                await sendMessage(message);
              } finally {
                this.reinitializing = false;
              }
            } else {
              throw error;
            }
          }
        };
        this._transport = transport;
        logger.debug(`${this.constructor.name} connected successfully`);
        return transport;
      }
      /**
       * Re-initialize the transport with a new session
       * This is called when the server returns 404 for a stale session
       */
      async reinitialize(transport) {
        logger.debug(`[SSE] Re-initialization triggered`);
      }
      /**
       * Close the underlying transport and clean up resources.
       */
      async closeConnection(_connection) {
        if (this._transport) {
          try {
            await this._transport.close();
          } catch (e) {
            logger.warn(`Error closing SSE transport: ${e}`);
          } finally {
            this._transport = null;
          }
        }
      }
    };
  }
});

// src/connectors/http.ts
var import_client, import_streamableHttp, HttpConnector;
var init_http = __esm({
  "src/connectors/http.ts"() {
    "use strict";
    import_client = require("@modelcontextprotocol/sdk/client/index.js");
    import_streamableHttp = require("@modelcontextprotocol/sdk/client/streamableHttp.js");
    init_logging();
    init_sse();
    init_base3();
    HttpConnector = class extends BaseConnector {
      static {
        __name(this, "HttpConnector");
      }
      baseUrl;
      headers;
      timeout;
      sseReadTimeout;
      clientInfo;
      preferSse;
      disableSseFallback;
      gatewayUrl;
      serverId;
      transportType = null;
      streamableTransport = null;
      constructor(baseUrl, opts = {}) {
        super(opts);
        this.baseUrl = baseUrl.replace(/\/$/, "");
        this.headers = { ...opts.headers ?? {} };
        if (opts.authToken) {
          this.headers.Authorization = `Bearer ${opts.authToken}`;
        }
        this.gatewayUrl = opts.gatewayUrl;
        this.serverId = opts.serverId;
        if (this.gatewayUrl) {
          this.headers["X-Target-URL"] = this.baseUrl;
          if (this.serverId) {
            this.headers["X-Server-Id"] = this.serverId;
          }
        }
        this.timeout = opts.timeout ?? 1e4;
        this.sseReadTimeout = opts.sseReadTimeout ?? 3e5;
        this.clientInfo = opts.clientInfo ?? {
          name: "http-connector",
          version: "1.0.0"
        };
        this.preferSse = opts.preferSse ?? false;
        this.disableSseFallback = opts.disableSseFallback ?? false;
      }
      /** Establish connection to the MCP implementation via HTTP (streamable or SSE). */
      async connect() {
        if (this.connected) {
          logger.debug("Already connected to MCP implementation");
          return;
        }
        const baseUrl = this.gatewayUrl ? this.gatewayUrl.replace(/\/$/, "") : this.baseUrl;
        if (this.preferSse) {
          logger.debug(`Connecting to MCP implementation via HTTP/SSE: ${baseUrl}`);
          await this.connectWithSse(baseUrl);
          return;
        }
        logger.debug(`Connecting to MCP implementation via HTTP: ${baseUrl}`);
        try {
          logger.info("\u{1F504} Attempting streamable HTTP transport...");
          await this.connectWithStreamableHttp(baseUrl);
          logger.info("\u2705 Successfully connected via streamable HTTP");
        } catch (err) {
          let fallbackReason = "Unknown error";
          let is401Error = false;
          if (err instanceof import_streamableHttp.StreamableHTTPError) {
            const streamableErr = err;
            is401Error = streamableErr.code === 401;
            if (streamableErr.code === 400 && streamableErr.message.includes("Missing session ID")) {
              fallbackReason = "Server requires session ID (FastMCP compatibility) - using SSE transport";
              logger.warn(`\u26A0\uFE0F  ${fallbackReason}`);
            } else if (streamableErr.code === 404 || streamableErr.code === 405) {
              fallbackReason = `Server returned ${streamableErr.code} - server likely doesn't support streamable HTTP`;
              logger.debug(fallbackReason);
            } else {
              fallbackReason = `Server returned ${streamableErr.code}: ${streamableErr.message}`;
              logger.debug(fallbackReason);
            }
          } else if (err instanceof Error) {
            const errorStr = err.toString();
            const errorMsg = err.message || "";
            is401Error = errorStr.includes("401") || errorMsg.includes("Unauthorized");
            if (errorStr.includes("Missing session ID") || errorStr.includes("Bad Request: Missing session ID") || errorMsg.includes("FastMCP session ID error")) {
              fallbackReason = "Server requires session ID (FastMCP compatibility) - using SSE transport";
              logger.warn(`\u26A0\uFE0F  ${fallbackReason}`);
            } else if (errorStr.includes("405 Method Not Allowed") || errorStr.includes("404 Not Found")) {
              fallbackReason = "Server doesn't support streamable HTTP (405/404)";
              logger.debug(fallbackReason);
            } else {
              fallbackReason = `Streamable HTTP failed: ${err.message}`;
              logger.debug(fallbackReason);
            }
          }
          if (is401Error) {
            logger.info("Authentication required - skipping SSE fallback");
            await this.cleanupResources();
            const authError = new Error("Authentication required");
            authError.code = 401;
            throw authError;
          }
          if (this.disableSseFallback) {
            logger.info("SSE fallback disabled - failing connection");
            await this.cleanupResources();
            throw new Error(`Streamable HTTP connection failed: ${fallbackReason}`);
          }
          logger.info("\u{1F504} Falling back to SSE transport...");
          try {
            await this.connectWithSse(baseUrl);
          } catch (sseErr) {
            logger.error(`Failed to connect with both transports:`);
            logger.error(`  Streamable HTTP: ${fallbackReason}`);
            logger.error(`  SSE: ${sseErr}`);
            await this.cleanupResources();
            const sseIs401 = sseErr?.message?.includes("401") || sseErr?.message?.includes("Unauthorized");
            if (sseIs401) {
              const authError = new Error("Authentication required");
              authError.code = 401;
              throw authError;
            }
            throw new Error(
              "Could not connect to server with any available transport"
            );
          }
        }
      }
      async connectWithStreamableHttp(baseUrl) {
        try {
          const streamableTransport = new import_streamableHttp.StreamableHTTPClientTransport(
            new URL(baseUrl),
            {
              authProvider: this.opts.authProvider,
              // ← Pass OAuth provider to SDK
              requestInit: {
                headers: this.headers
              },
              // Pass through reconnection options
              reconnectionOptions: {
                maxReconnectionDelay: 3e4,
                initialReconnectionDelay: 1e3,
                reconnectionDelayGrowFactor: 1.5,
                maxRetries: 2
              }
              // Don't pass sessionId - let the SDK generate it automatically during connect()
            }
          );
          let transport = streamableTransport;
          if (this.opts.wrapTransport) {
            const serverId = this.baseUrl;
            transport = this.opts.wrapTransport(
              transport,
              serverId
            );
          }
          const clientOptions = {
            ...this.opts.clientOptions || {},
            capabilities: {
              ...this.opts.clientOptions?.capabilities || {},
              roots: { listChanged: true },
              // Always advertise roots capability
              // Add sampling capability if callback is provided
              ...this.opts.samplingCallback ? { sampling: {} } : {},
              // Add elicitation capability if callback is provided
              ...this.opts.elicitationCallback ? { elicitation: { form: {}, url: {} } } : {}
            }
          };
          logger.debug(
            `Creating Client with capabilities:`,
            JSON.stringify(clientOptions.capabilities, null, 2)
          );
          this.client = new import_client.Client(this.clientInfo, clientOptions);
          this.setupRootsHandler();
          logger.debug("Roots handler registered before connect");
          try {
            await this.client.connect(transport, {
              timeout: this.timeout
            });
            const sessionId = streamableTransport.sessionId;
            if (sessionId) {
              logger.debug(`Session ID obtained: ${sessionId}`);
            } else {
              logger.warn(
                "Session ID not available after connect - this may cause issues with SSE stream"
              );
            }
          } catch (connectErr) {
            if (connectErr instanceof Error) {
              const errMsg = connectErr.message || connectErr.toString();
              if (errMsg.includes("Missing session ID") || errMsg.includes("Bad Request: Missing session ID") || errMsg.includes("Mcp-Session-Id header is required")) {
                const wrappedError = new Error(
                  `Session ID error: ${errMsg}. The SDK should automatically extract session ID from initialize response.`
                );
                wrappedError.cause = connectErr;
                throw wrappedError;
              }
            }
            throw connectErr;
          }
          this.streamableTransport = streamableTransport;
          this.connectionManager = {
            stop: /* @__PURE__ */ __name(async () => {
              if (this.streamableTransport) {
                try {
                  await this.streamableTransport.terminateSession();
                  await this.streamableTransport.close();
                } catch (e) {
                  logger.warn(`Error closing Streamable HTTP transport: ${e}`);
                } finally {
                  this.streamableTransport = null;
                }
              }
            }, "stop")
          };
          this.connected = true;
          this.transportType = "streamable-http";
          this.setupNotificationHandler();
          this.setupSamplingHandler();
          this.setupElicitationHandler();
          logger.debug(
            `Successfully connected to MCP implementation via streamable HTTP: ${baseUrl}`
          );
          this.trackConnectorInit({
            serverUrl: this.baseUrl,
            publicIdentifier: `${this.baseUrl} (streamable-http)`
          });
        } catch (err) {
          await this.cleanupResources();
          throw err;
        }
      }
      async connectWithSse(baseUrl) {
        try {
          this.connectionManager = new SseConnectionManager(baseUrl, {
            authProvider: this.opts.authProvider,
            // ← Pass OAuth provider to SDK (same as streamable HTTP)
            requestInit: {
              headers: this.headers
            }
          });
          let transport = await this.connectionManager.start();
          if (this.opts.wrapTransport) {
            const serverId = this.baseUrl;
            transport = this.opts.wrapTransport(transport, serverId);
          }
          const clientOptions = {
            ...this.opts.clientOptions || {},
            capabilities: {
              ...this.opts.clientOptions?.capabilities || {},
              roots: { listChanged: true },
              // Always advertise roots capability
              // Add sampling capability if callback is provided
              ...this.opts.samplingCallback ? { sampling: {} } : {},
              // Add elicitation capability if callback is provided
              ...this.opts.elicitationCallback ? { elicitation: { form: {}, url: {} } } : {}
            }
          };
          logger.debug(
            `Creating Client with capabilities (SSE):`,
            JSON.stringify(clientOptions.capabilities, null, 2)
          );
          this.client = new import_client.Client(this.clientInfo, clientOptions);
          this.setupRootsHandler();
          logger.debug("Roots handler registered before connect (SSE)");
          await this.client.connect(transport);
          this.connected = true;
          this.transportType = "sse";
          this.setupNotificationHandler();
          this.setupSamplingHandler();
          this.setupElicitationHandler();
          logger.debug(
            `Successfully connected to MCP implementation via HTTP/SSE: ${baseUrl}`
          );
          this.trackConnectorInit({
            serverUrl: this.baseUrl,
            publicIdentifier: `${this.baseUrl} (sse)`
          });
        } catch (err) {
          await this.cleanupResources();
          throw err;
        }
      }
      get publicIdentifier() {
        return {
          type: "http",
          url: this.baseUrl,
          transport: this.transportType || "unknown"
        };
      }
      /**
       * Get the transport type being used (streamable-http or sse)
       */
      getTransportType() {
        return this.transportType;
      }
    };
  }
});

// src/task_managers/stdio.ts
var import_stdio, StdioConnectionManager;
var init_stdio = __esm({
  "src/task_managers/stdio.ts"() {
    "use strict";
    import_stdio = require("@modelcontextprotocol/sdk/client/stdio.js");
    init_logging();
    init_base4();
    StdioConnectionManager = class extends ConnectionManager {
      static {
        __name(this, "StdioConnectionManager");
      }
      serverParams;
      errlog;
      _transport = null;
      /**
       * Create a new stdio connection manager.
       *
       * @param serverParams Parameters for the stdio server process.
       * @param errlog       Stream to which the server's stderr should be piped.
       *                     Defaults to `process.stderr`.
       */
      constructor(serverParams, errlog = process.stderr) {
        super();
        this.serverParams = serverParams;
        this.errlog = errlog;
      }
      /**
       * Establish the stdio connection by spawning the server process and starting
       * the SDK's transport. Returns the live `StdioClientTransport` instance.
       */
      async establishConnection() {
        this._transport = new import_stdio.StdioClientTransport(this.serverParams);
        if (this._transport.stderr && typeof this._transport.stderr.pipe === "function") {
          this._transport.stderr.pipe(
            this.errlog
          );
        }
        logger.debug(`${this.constructor.name} connected successfully`);
        return this._transport;
      }
      /**
       * Close the stdio connection, making sure the transport cleans up the child
       * process and associated resources.
       */
      async closeConnection(_connection) {
        if (this._transport) {
          try {
            await this._transport.close();
          } catch (e) {
            logger.warn(`Error closing stdio transport: ${e}`);
          } finally {
            this._transport = null;
          }
        }
      }
    };
  }
});

// src/connectors/stdio.ts
var import_node_process, import_client2, StdioConnector;
var init_stdio2 = __esm({
  "src/connectors/stdio.ts"() {
    "use strict";
    import_node_process = __toESM(require("process"), 1);
    import_client2 = require("@modelcontextprotocol/sdk/client/index.js");
    init_logging();
    init_stdio();
    init_base3();
    StdioConnector = class extends BaseConnector {
      static {
        __name(this, "StdioConnector");
      }
      command;
      args;
      env;
      errlog;
      clientInfo;
      constructor({
        command = "npx",
        args = [],
        env,
        errlog = import_node_process.default.stderr,
        ...rest
      } = {}) {
        super(rest);
        this.command = command;
        this.args = args;
        this.env = env;
        this.errlog = errlog;
        this.clientInfo = rest.clientInfo ?? {
          name: "stdio-connector",
          version: "1.0.0"
        };
      }
      /** Establish connection to the MCP implementation. */
      async connect() {
        if (this.connected) {
          logger.debug("Already connected to MCP implementation");
          return;
        }
        logger.debug(`Connecting to MCP implementation via stdio: ${this.command}`);
        try {
          let mergedEnv;
          if (this.env) {
            mergedEnv = {};
            for (const [key, value] of Object.entries(import_node_process.default.env)) {
              if (value !== void 0) {
                mergedEnv[key] = value;
              }
            }
            Object.assign(mergedEnv, this.env);
          }
          const serverParams = {
            command: this.command,
            args: this.args,
            env: mergedEnv
          };
          this.connectionManager = new StdioConnectionManager(
            serverParams,
            this.errlog
          );
          const transport = await this.connectionManager.start();
          const clientOptions = {
            ...this.opts.clientOptions || {},
            capabilities: {
              ...this.opts.clientOptions?.capabilities || {},
              roots: { listChanged: true },
              // Always advertise roots capability
              // Add sampling capability if callback is provided
              ...this.opts.samplingCallback ? { sampling: {} } : {},
              // Add elicitation capability if callback is provided
              ...this.opts.elicitationCallback ? { elicitation: { form: {}, url: {} } } : {}
            }
          };
          this.client = new import_client2.Client(this.clientInfo, clientOptions);
          await this.client.connect(transport);
          this.connected = true;
          this.setupNotificationHandler();
          this.setupRootsHandler();
          this.setupSamplingHandler();
          this.setupElicitationHandler();
          logger.debug(
            `Successfully connected to MCP implementation: ${this.command}`
          );
          this.trackConnectorInit({
            serverCommand: this.command,
            serverArgs: this.args,
            publicIdentifier: `${this.command} ${this.args.join(" ")}`
          });
        } catch (err) {
          logger.error(`Failed to connect to MCP implementation: ${err}`);
          await this.cleanupResources();
          throw err;
        }
      }
      get publicIdentifier() {
        return {
          type: "stdio",
          "command&args": `${this.command} ${this.args.join(" ")}`
        };
      }
    };
  }
});

// src/config.ts
function loadConfigFile(filepath) {
  const raw = (0, import_node_fs.readFileSync)(filepath, "utf-8");
  return JSON.parse(raw);
}
function createConnectorFromConfig(serverConfig, connectorOptions) {
  if ("command" in serverConfig && "args" in serverConfig) {
    return new StdioConnector({
      command: serverConfig.command,
      args: serverConfig.args,
      env: serverConfig.env,
      ...connectorOptions
    });
  }
  if ("url" in serverConfig) {
    const transport = serverConfig.transport || "http";
    return new HttpConnector(serverConfig.url, {
      headers: serverConfig.headers,
      authToken: serverConfig.auth_token || serverConfig.authToken,
      // Only force SSE if explicitly requested
      preferSse: serverConfig.preferSse || transport === "sse",
      // Disable SSE fallback if explicitly disabled in config
      disableSseFallback: serverConfig.disableSseFallback,
      // Pass clientInfo if provided in server config
      clientInfo: serverConfig.clientInfo,
      ...connectorOptions
    });
  }
  throw new Error("Cannot determine connector type from config");
}
var import_node_fs;
var init_config = __esm({
  "src/config.ts"() {
    "use strict";
    import_node_fs = require("fs");
    init_http();
    init_stdio2();
    __name(loadConfigFile, "loadConfigFile");
    __name(createConnectorFromConfig, "createConnectorFromConfig");
  }
});

// src/client.ts
var client_exports = {};
__export(client_exports, {
  BaseCodeExecutor: () => BaseCodeExecutor,
  E2BCodeExecutor: () => E2BCodeExecutor,
  MCPClient: () => MCPClient,
  MCPSession: () => MCPSession,
  VMCodeExecutor: () => VMCodeExecutor,
  isVMAvailable: () => isVMAvailable
});
var import_node_fs2, import_node_path, MCPClient;
var init_client = __esm({
  "src/client.ts"() {
    "use strict";
    import_node_fs2 = __toESM(require("fs"), 1);
    import_node_path = __toESM(require("path"), 1);
    init_base();
    init_codeExecutor();
    init_codeMode();
    init_config();
    init_logging();
    init_session();
    init_telemetry();
    init_version();
    init_codeExecutor();
    init_session();
    MCPClient = class _MCPClient extends BaseMCPClient {
      static {
        __name(this, "MCPClient");
      }
      /**
       * Get the mcp-use package version.
       * Works in all environments (Node.js, browser, Cloudflare Workers, Deno, etc.)
       */
      static getPackageVersion() {
        return getPackageVersion();
      }
      codeMode = false;
      _codeExecutor = null;
      _customCodeExecutor = null;
      _codeExecutorConfig = "vm";
      _executorOptions;
      _samplingCallback;
      _elicitationCallback;
      constructor(config, options) {
        if (config) {
          if (typeof config === "string") {
            super(loadConfigFile(config));
          } else {
            super(config);
          }
        } else {
          super();
        }
        let codeModeEnabled = false;
        let executorConfig = "vm";
        let executorOptions;
        if (options?.codeMode) {
          if (typeof options.codeMode === "boolean") {
            codeModeEnabled = options.codeMode;
          } else {
            codeModeEnabled = options.codeMode.enabled;
            executorConfig = options.codeMode.executor ?? "vm";
            executorOptions = options.codeMode.executorOptions;
          }
        }
        this.codeMode = codeModeEnabled;
        this._codeExecutorConfig = executorConfig;
        this._executorOptions = executorOptions;
        this._samplingCallback = options?.samplingCallback;
        this._elicitationCallback = options?.elicitationCallback;
        if (this.codeMode) {
          this._setupCodeModeConnector();
        }
        this._trackClientInit();
      }
      _trackClientInit() {
        const servers = Object.keys(this.config.mcpServers ?? {});
        const hasSamplingCallback = !!this._samplingCallback;
        const hasElicitationCallback = !!this._elicitationCallback;
        Tel.getInstance().trackMCPClientInit({
          codeMode: this.codeMode,
          sandbox: false,
          // Sandbox not supported in TS yet
          allCallbacks: hasSamplingCallback && hasElicitationCallback,
          verify: false,
          // No verify option in TS client
          servers,
          numServers: servers.length,
          isBrowser: false
          // Node.js MCPClient
        }).catch((e) => logger.debug(`Failed to track MCPClient init: ${e}`));
      }
      static fromDict(cfg, options) {
        return new _MCPClient(cfg, options);
      }
      static fromConfigFile(path2, options) {
        return new _MCPClient(loadConfigFile(path2), options);
      }
      /**
       * Save configuration to a file (Node.js only)
       */
      saveConfig(filepath) {
        const dir = import_node_path.default.dirname(filepath);
        if (!import_node_fs2.default.existsSync(dir)) {
          import_node_fs2.default.mkdirSync(dir, { recursive: true });
        }
        import_node_fs2.default.writeFileSync(filepath, JSON.stringify(this.config, null, 2), "utf-8");
      }
      /**
       * Create a connector from server configuration (Node.js version)
       * Supports all connector types including StdioConnector
       */
      createConnectorFromConfig(serverConfig) {
        return createConnectorFromConfig(serverConfig, {
          samplingCallback: this._samplingCallback,
          elicitationCallback: this._elicitationCallback
        });
      }
      _setupCodeModeConnector() {
        logger.debug("Code mode connector initialized as internal meta server");
        const connector = new CodeModeConnector(this);
        const session = new MCPSession(connector);
        this.sessions["code_mode"] = session;
        this.activeSessions.push("code_mode");
      }
      _ensureCodeExecutor() {
        if (!this._codeExecutor) {
          const config = this._codeExecutorConfig;
          if (config instanceof BaseCodeExecutor) {
            this._codeExecutor = config;
          } else if (typeof config === "function") {
            this._customCodeExecutor = config;
            throw new Error(
              "Custom executor function should be handled in executeCode"
            );
          } else if (config === "e2b") {
            const opts = this._executorOptions;
            if (!opts?.apiKey) {
              logger.warn("E2B executor requires apiKey. Falling back to VM.");
              try {
                this._codeExecutor = new VMCodeExecutor(
                  this,
                  this._executorOptions
                );
              } catch (error) {
                throw new Error(
                  "VM executor is not available in this environment and E2B API key is not provided. Please provide an E2B API key or run in a Node.js environment."
                );
              }
            } else {
              this._codeExecutor = new E2BCodeExecutor(this, opts);
            }
          } else {
            try {
              this._codeExecutor = new VMCodeExecutor(
                this,
                this._executorOptions
              );
            } catch (error) {
              const e2bOpts = this._executorOptions;
              const e2bApiKey = e2bOpts?.apiKey || process.env.E2B_API_KEY;
              if (e2bApiKey) {
                logger.info(
                  "VM executor not available in this environment. Falling back to E2B."
                );
                this._codeExecutor = new E2BCodeExecutor(this, {
                  ...e2bOpts,
                  apiKey: e2bApiKey
                });
              } else {
                throw new Error(
                  "VM executor is not available in this environment. Please provide an E2B API key via executorOptions or E2B_API_KEY environment variable, or run in a Node.js environment."
                );
              }
            }
          }
        }
        return this._codeExecutor;
      }
      /**
       * Execute code in code mode
       */
      async executeCode(code, timeout) {
        if (!this.codeMode) {
          throw new Error("Code execution mode is not enabled");
        }
        if (this._customCodeExecutor) {
          return this._customCodeExecutor(code, timeout);
        }
        return this._ensureCodeExecutor().execute(code, timeout);
      }
      /**
       * Search available tools (used by code mode)
       */
      async searchTools(query = "", detailLevel = "full") {
        if (!this.codeMode) {
          throw new Error("Code execution mode is not enabled");
        }
        return this._ensureCodeExecutor().createSearchToolsFunction()(
          query,
          detailLevel
        );
      }
      /**
       * Override getServerNames to exclude internal code_mode server
       */
      getServerNames() {
        const isCodeModeEnabled = this.codeMode;
        return super.getServerNames().filter((name) => {
          return !isCodeModeEnabled || name !== "code_mode";
        });
      }
      /**
       * Close the client and clean up resources including code executors.
       * This ensures E2B sandboxes and other resources are properly released.
       */
      async close() {
        if (this._codeExecutor) {
          await this._codeExecutor.cleanup();
          this._codeExecutor = null;
        }
        await this.closeAllSessions();
      }
    };
  }
});

// src/agents/display.ts
var display_exports = {};
__export(display_exports, {
  extractCodeFromToolInput: () => extractCodeFromToolInput,
  extractToolMessageContent: () => extractToolMessageContent,
  formatSearchToolsAsTree: () => formatSearchToolsAsTree,
  handleToolEnd: () => handleToolEnd,
  handleToolStart: () => handleToolStart,
  parseExecuteCodeResult: () => parseExecuteCodeResult,
  prettyStreamEvents: () => prettyStreamEvents,
  printBox: () => printBox,
  renderContent: () => renderContent,
  unwrapToolInput: () => unwrapToolInput
});
function highlightCode(content, language) {
  if (!highlight) {
    return content;
  }
  try {
    return highlight(content, {
      language: language ?? "javascript",
      ignoreIllegals: true
    });
  } catch {
    return content;
  }
}
function stripAnsi(str) {
  if (stripVTControlCharacters) {
    return stripVTControlCharacters(str);
  }
  return str.replace(/\x1b\[[0-9;]*m/g, "");
}
function wrapAnsiLine(line, maxWidth) {
  const stripped = stripAnsi(line);
  if (stripped.length <= maxWidth) return [line];
  const result = [];
  let visibleCount = 0;
  let current = "";
  let i = 0;
  while (i < line.length) {
    const char = line[i];
    if (char === "\x1B") {
      let sequence = char;
      i++;
      while (i < line.length) {
        const nextChar = line[i];
        sequence += nextChar;
        i++;
        if (nextChar === "m") break;
      }
      current += sequence;
      continue;
    }
    current += char;
    visibleCount++;
    i++;
    if (visibleCount >= maxWidth) {
      result.push(current);
      current = "";
      visibleCount = 0;
    }
  }
  if (current) result.push(current);
  return result;
}
function printBox(content, title, language, bgColor = false) {
  const width = TERMINAL_WIDTH;
  let displayContent = content;
  if (language) {
    try {
      displayContent = highlightCode(content, language);
    } catch {
    }
  }
  const lines = displayContent.split("\n").flatMap((line) => wrapAnsiLine(line, width - 4));
  console.log(chalkHelper.gray("\u250C" + "\u2500".repeat(width - 2) + "\u2510"));
  if (title) {
    const stripped = stripAnsi(title);
    const lineText = `${title} `;
    const padding = Math.max(0, width - 4 - stripped.length - 2);
    console.log(
      chalkHelper.gray("\u2502 ") + chalkHelper.bold.white(lineText) + " ".repeat(padding) + chalkHelper.gray(" \u2502")
    );
    console.log(chalkHelper.gray("\u251C" + "\u2500".repeat(width - 2) + "\u2524"));
  }
  lines.forEach((line) => {
    const stripped = stripAnsi(line);
    const padding = Math.max(0, width - 4 - stripped.length);
    const finalLine = bgColor ? chalkHelper.bgGray(line + " ".repeat(padding)) : line + " ".repeat(padding);
    console.log(chalkHelper.gray("\u2502 ") + finalLine + chalkHelper.gray(" \u2502"));
  });
  console.log(chalkHelper.gray("\u2514" + "\u2500".repeat(width - 2) + "\u2518"));
}
function extractCodeFromToolInput(input) {
  if (typeof input === "object" && input !== null && "code" in input) {
    const inputObj = input;
    return typeof inputObj.code === "string" ? inputObj.code : null;
  }
  return null;
}
function isExecuteCodeResult(obj) {
  if (typeof obj !== "object" || obj === null) return false;
  const result = obj;
  return "result" in result && "logs" in result && Array.isArray(result.logs) && "execution_time" in result && typeof result.execution_time === "number" && "error" in result && (typeof result.error === "string" || result.error === null);
}
function parseExecuteCodeResult(output) {
  try {
    if (typeof output === "string") {
      const parsed = JSON.parse(output);
      if (isExecuteCodeResult(parsed)) {
        return parsed;
      }
    }
    if (isExecuteCodeResult(output)) {
      return output;
    }
  } catch (e) {
  }
  return null;
}
function renderContent(content) {
  if (content === null || content === void 0) {
    return "null";
  }
  if (typeof content === "object") {
    return JSON.stringify(content, null, 2);
  }
  return String(content);
}
function unwrapToolInput(input) {
  if (typeof input === "object" && input !== null && "input" in input) {
    const inputObj = input;
    if (typeof inputObj.input === "string") {
      try {
        return JSON.parse(inputObj.input);
      } catch (e) {
        return inputObj.input;
      }
    }
  }
  return input;
}
function handleToolStart(event) {
  const toolName = event.name || "unknown";
  let input = event.data?.input || {};
  input = unwrapToolInput(input);
  const code = extractCodeFromToolInput(input);
  if (code) {
    printBox(code, `${toolName} - input`, "javascript", false);
    const otherParams = { ...input };
    delete otherParams.code;
    if (Object.keys(otherParams).length > 0) {
      printBox(renderContent(otherParams), "Other Parameters", "json", false);
    }
  } else {
    printBox(renderContent(input), `${toolName} - input`, "json", false);
  }
}
function extractToolMessageContent(output) {
  try {
    if (typeof output === "object" && output !== null && "name" in output && "content" in output) {
      const outputObj = output;
      const toolName = (typeof outputObj.name === "string" ? outputObj.name : null) || "unknown";
      const lcKwargs = outputObj.lc_kwargs;
      const status = lcKwargs?.status || outputObj.status || "unknown";
      let content = outputObj.content;
      if (typeof content === "string") {
        try {
          content = JSON.parse(content);
        } catch (e) {
        }
      }
      return { toolName, status, content };
    }
  } catch (e) {
  }
  return null;
}
function formatSearchToolsAsTree(tools, meta, query) {
  const metaLines = [];
  if (meta) {
    if (meta.total_tools !== void 0) {
      metaLines.push(`Total tools: ${meta.total_tools}`);
    }
    if (meta.namespaces && meta.namespaces.length > 0) {
      metaLines.push(`Namespaces: ${meta.namespaces.join(", ")}`);
    }
    if (meta.result_count !== void 0) {
      metaLines.push(`Results: ${meta.result_count}`);
    }
  }
  if (!Array.isArray(tools) || tools.length === 0) {
    const noResultsMsg = query ? `No tools found for query "${query}"` : "(no tools found)";
    if (metaLines.length > 0) {
      return `${metaLines.join("\n")}

${noResultsMsg}`;
    }
    return noResultsMsg;
  }
  const toolsByServer = {};
  for (const tool of tools) {
    const server = tool.server || "unknown";
    if (!toolsByServer[server]) {
      toolsByServer[server] = [];
    }
    toolsByServer[server].push(tool);
  }
  const lines = [];
  if (meta) {
    if (meta.total_tools !== void 0) {
      lines.push(`Total tools: ${meta.total_tools}`);
    }
    if (meta.namespaces && meta.namespaces.length > 0) {
      lines.push(`Namespaces: ${meta.namespaces.join(", ")}`);
    }
    if (meta.result_count !== void 0) {
      lines.push(`Results: ${meta.result_count}`);
    }
    if (lines.length > 0) {
      lines.push("");
    }
  }
  const servers = Object.keys(toolsByServer).sort();
  for (let i = 0; i < servers.length; i++) {
    const server = servers[i];
    const serverTools = toolsByServer[server];
    const isLastServer = i === servers.length - 1;
    const serverPrefix = isLastServer ? "\u2514\u2500" : "\u251C\u2500";
    lines.push(
      `${serverPrefix} ${chalkHelper.cyan(server)} (${serverTools.length} tools)`
    );
    for (let j = 0; j < serverTools.length; j++) {
      const tool = serverTools[j];
      const isLastTool = j === serverTools.length - 1;
      const indent = isLastServer ? "  " : "\u2502 ";
      const toolPrefix = isLastTool ? "\u2514\u2500" : "\u251C\u2500";
      const toolLine = `${indent}${toolPrefix} ${tool.name}`;
      lines.push(toolLine);
      if (tool.description) {
        const descAlign = isLastTool ? "   " : "\u2502  ";
        const descriptionIndent = `${indent}${descAlign}`;
        const indentLength = stripAnsi(descriptionIndent).length;
        const availableWidth = Math.max(40, TERMINAL_WIDTH - indentLength - 4);
        const words = tool.description.split(/(\s+)/);
        const wrappedLines = [];
        let currentLine = "";
        for (const word of words) {
          const testLine = currentLine + word;
          if (stripAnsi(testLine).length <= availableWidth) {
            currentLine = testLine;
          } else {
            if (currentLine) {
              wrappedLines.push(currentLine.trimEnd());
            }
            currentLine = word.trimStart();
          }
        }
        if (currentLine) {
          wrappedLines.push(currentLine.trimEnd());
        }
        for (const descLine of wrappedLines) {
          lines.push(`${descriptionIndent}${chalkHelper.dim(descLine)}`);
        }
      }
    }
  }
  return lines.join("\n");
}
function handleToolEnd(event) {
  const output = event.data?.output;
  const toolMessage = extractToolMessageContent(output);
  if (toolMessage) {
    const { toolName, status, content } = toolMessage;
    if (toolName === "execute_code") {
      let actualContent = content;
      if (typeof content === "object" && content !== null && "content" in content) {
        const innerContent = content.content;
        if (Array.isArray(innerContent) && innerContent.length > 0) {
          if (innerContent[0].type === "text" && innerContent[0].text) {
            actualContent = innerContent[0].text;
          }
        }
      }
      const execResult2 = parseExecuteCodeResult(actualContent);
      if (execResult2) {
        const timeMs = execResult2.execution_time ? Math.round(execResult2.execution_time * 1e3) : 0;
        const timeStr = `${timeMs}ms`;
        const isError2 = execResult2.error !== null && execResult2.error !== void 0 && execResult2.error !== "";
        const statusText = isError2 ? chalkHelper.red("error") : chalkHelper.green("success");
        const title2 = `${toolName} - ${statusText} - ${timeStr}`;
        if (execResult2.result !== null && execResult2.result !== void 0) {
          const resultStr = renderContent(execResult2.result);
          const language3 = typeof execResult2.result === "object" ? "json" : void 0;
          printBox(resultStr, title2, language3, false);
        } else {
          printBox("(no result)", title2, void 0, false);
        }
        if (execResult2.logs && execResult2.logs.length > 0) {
          printBox(execResult2.logs.join("\n"), `Logs`, void 0, false);
        }
        if (execResult2.error) {
          printBox(
            execResult2.error,
            chalkHelper.red("Error"),
            void 0,
            false
          );
        }
        return;
      }
    }
    if (toolName === "search_tools") {
      const toolInput = event.data?.input;
      const query = toolInput?.query;
      let actualContent = content;
      if (typeof content === "object" && content !== null && !Array.isArray(content) && "content" in content) {
        const innerContent = content.content;
        if (Array.isArray(innerContent) && innerContent.length > 0) {
          if (innerContent[0].type === "text" && innerContent[0].text) {
            try {
              actualContent = JSON.parse(innerContent[0].text);
            } catch (e) {
              actualContent = innerContent[0].text;
            }
          }
        }
      }
      if (typeof actualContent === "object" && actualContent !== null && !Array.isArray(actualContent) && "results" in actualContent && Array.isArray(actualContent.results)) {
        const results = actualContent.results;
        const contentWithMeta = actualContent;
        const meta = contentWithMeta.meta;
        const treeStr = formatSearchToolsAsTree(results, meta, query);
        const statusText = status === "success" ? chalk.green("Success") : chalk.red("Error");
        const title2 = `${statusText}: ${toolName} - Result`;
        printBox(treeStr, title2, void 0, false);
        return;
      }
      if (Array.isArray(actualContent)) {
        const treeStr = formatSearchToolsAsTree(
          actualContent,
          void 0,
          query
        );
        const statusText = status === "success" ? chalk.green("Success") : chalk.red("Error");
        const title2 = `${statusText}: ${toolName} - Result`;
        printBox(treeStr, title2, void 0, false);
        return;
      }
    }
    const contentObj = typeof content === "object" && content !== null ? content : null;
    const isError = contentObj && "isError" in contentObj && contentObj.isError === true || status === "error";
    let displayContent = content;
    if (typeof content === "object" && content !== null && "content" in content) {
      displayContent = content.content;
      if (Array.isArray(displayContent) && displayContent.length > 0) {
        if (displayContent[0].type === "text" && displayContent[0].text) {
          displayContent = displayContent[0].text;
        }
      }
    }
    const contentStr = renderContent(displayContent);
    const language2 = typeof displayContent === "object" ? "json" : void 0;
    const statusLabel = status === "success" ? chalkHelper.green("Success") : isError ? chalkHelper.red("Error") : "Result";
    const title = `${statusLabel}: ${toolName} - Result`;
    printBox(contentStr, title, language2, false);
    return;
  }
  const execResult = parseExecuteCodeResult(output);
  if (execResult) {
    const timeMs = execResult.execution_time ? Math.round(execResult.execution_time * 1e3) : 0;
    const timeStr = `${timeMs}ms`;
    if (execResult.result !== null && execResult.result !== void 0) {
      const resultStr = renderContent(execResult.result);
      const language2 = typeof execResult.result === "object" ? "json" : void 0;
      printBox(resultStr, `Result - ${timeStr}`, language2, false);
    }
    if (execResult.logs && execResult.logs.length > 0) {
      printBox(execResult.logs.join("\n"), `Logs`, void 0, false);
    }
    if (execResult.error) {
      printBox(execResult.error, chalkHelper.red("Error"), void 0, false);
    }
    return;
  }
  const outputStr = renderContent(output);
  const language = typeof output === "object" ? "json" : void 0;
  printBox(outputStr, "Result", language, false);
}
async function* prettyStreamEvents(streamEventsGenerator) {
  let finalResponse = "";
  let isFirstTextChunk = true;
  let hasStreamedText = false;
  for await (const event of streamEventsGenerator) {
    if (event.event === "on_tool_start") {
      if (hasStreamedText) {
        process.stdout.write("\n");
        hasStreamedText = false;
        isFirstTextChunk = true;
      }
      handleToolStart(event);
    } else if (event.event === "on_tool_end") {
      handleToolEnd(event);
    } else if (event.event === "on_chat_model_stream") {
      if (event.data?.chunk?.text) {
        const text = event.data.chunk.text;
        if (typeof text === "string" && text.length > 0) {
          if (isFirstTextChunk) {
            process.stdout.write("\n\u{1F916} ");
            isFirstTextChunk = false;
          }
          process.stdout.write(text);
          finalResponse += text;
          hasStreamedText = true;
        }
      }
    }
    yield;
  }
  return finalResponse;
}
var chalk, highlight, stripVTControlCharacters, displayPackagesWarned, isNode, TERMINAL_WIDTH, chalkHelper;
var init_display = __esm({
  "src/agents/display.ts"() {
    "use strict";
    chalk = null;
    highlight = null;
    stripVTControlCharacters = null;
    displayPackagesWarned = false;
    isNode = typeof process !== "undefined" && process.versions?.node;
    (async () => {
      if (isNode) {
        try {
          const utilModule = await import("util");
          stripVTControlCharacters = utilModule.stripVTControlCharacters;
        } catch {
        }
      }
      try {
        const chalkModule = await import("chalk");
        chalk = chalkModule.default;
      } catch {
      }
      try {
        const cliHighlightModule = await import("cli-highlight");
        highlight = cliHighlightModule.highlight;
      } catch {
      }
      if (isNode && (!chalk || !highlight)) {
        if (!displayPackagesWarned) {
          displayPackagesWarned = true;
          console.warn(
            "\n\u2728 For enhanced console output with colors and syntax highlighting, install:\n\n  npm install chalk cli-highlight\n  # or\n  pnpm add chalk cli-highlight\n"
          );
        }
      }
    })();
    TERMINAL_WIDTH = process.stdout.columns || 120;
    chalkHelper = {
      gray: /* @__PURE__ */ __name((str) => chalk?.gray(str) ?? str, "gray"),
      bold: {
        white: /* @__PURE__ */ __name((str) => chalk?.bold?.white(str) ?? str, "white")
      },
      bgGray: /* @__PURE__ */ __name((str) => chalk?.bgGray(str) ?? str, "bgGray"),
      cyan: /* @__PURE__ */ __name((str) => chalk?.cyan(str) ?? str, "cyan"),
      dim: /* @__PURE__ */ __name((str) => chalk?.dim(str) ?? str, "dim"),
      red: /* @__PURE__ */ __name((str) => chalk?.red(str) ?? str, "red"),
      green: /* @__PURE__ */ __name((str) => chalk?.green(str) ?? str, "green")
    };
    __name(highlightCode, "highlightCode");
    __name(stripAnsi, "stripAnsi");
    __name(wrapAnsiLine, "wrapAnsiLine");
    __name(printBox, "printBox");
    __name(extractCodeFromToolInput, "extractCodeFromToolInput");
    __name(isExecuteCodeResult, "isExecuteCodeResult");
    __name(parseExecuteCodeResult, "parseExecuteCodeResult");
    __name(renderContent, "renderContent");
    __name(unwrapToolInput, "unwrapToolInput");
    __name(handleToolStart, "handleToolStart");
    __name(extractToolMessageContent, "extractToolMessageContent");
    __name(formatSearchToolsAsTree, "formatSearchToolsAsTree");
    __name(handleToolEnd, "handleToolEnd");
    __name(prettyStreamEvents, "prettyStreamEvents");
  }
});

// src/react/rpc-logger.ts
var rpc_logger_exports = {};
__export(rpc_logger_exports, {
  clearRpcLogs: () => clearRpcLogs,
  getAllRpcLogs: () => getAllRpcLogs,
  getRpcLogs: () => getRpcLogs,
  subscribeToRpcLogs: () => subscribeToRpcLogs,
  wrapTransportForLogging: () => wrapTransportForLogging
});
function getRpcLogs(serverId) {
  return rpcLogStore.getLogsForServer(serverId);
}
function getAllRpcLogs() {
  return rpcLogStore.getAllLogs();
}
function subscribeToRpcLogs(listener) {
  return rpcLogStore.subscribe(listener);
}
function clearRpcLogs(serverId) {
  rpcLogStore.clear(serverId);
}
function wrapTransportForLogging(transport, serverId) {
  class LoggingTransport {
    constructor(inner) {
      this.inner = inner;
      this.inner.onmessage = (message, extra) => {
        rpcLogStore.publish({
          serverId,
          direction: "receive",
          timestamp: (/* @__PURE__ */ new Date()).toISOString(),
          message
        });
        this.onmessage?.(message, extra);
      };
      this.inner.onclose = () => {
        this.onclose?.();
      };
      this.inner.onerror = (error) => {
        this.onerror?.(error);
      };
    }
    static {
      __name(this, "LoggingTransport");
    }
    onclose;
    onerror;
    onmessage;
    async start() {
      if (typeof this.inner.start === "function") {
        await this.inner.start();
      }
    }
    async send(message, options) {
      rpcLogStore.publish({
        serverId,
        direction: "send",
        timestamp: (/* @__PURE__ */ new Date()).toISOString(),
        message
      });
      await this.inner.send(message, options);
    }
    async close() {
      await this.inner.close();
    }
    get sessionId() {
      return this.inner.sessionId;
    }
    setProtocolVersion(version) {
      if (typeof this.inner.setProtocolVersion === "function") {
        this.inner.setProtocolVersion(version);
      }
    }
  }
  return new LoggingTransport(transport);
}
var RpcLogStore, rpcLogStore;
var init_rpc_logger = __esm({
  "src/react/rpc-logger.ts"() {
    "use strict";
    RpcLogStore = class {
      static {
        __name(this, "RpcLogStore");
      }
      logs = [];
      listeners = /* @__PURE__ */ new Set();
      maxLogs = 1e3;
      publish(entry) {
        console.log(
          "[RPC Logger] Publishing log:",
          entry.direction,
          entry.serverId,
          entry.message?.method
        );
        this.logs.push(entry);
        if (this.logs.length > this.maxLogs) {
          this.logs = this.logs.slice(-this.maxLogs);
        }
        console.log(
          "[RPC Logger] Total logs:",
          this.logs.length,
          "Listeners:",
          this.listeners.size
        );
        this.listeners.forEach((listener) => {
          try {
            listener(entry);
          } catch (err) {
            console.error("[RPC Logger] Listener error:", err);
          }
        });
      }
      subscribe(listener) {
        this.listeners.add(listener);
        return () => this.listeners.delete(listener);
      }
      getLogsForServer(serverId) {
        return this.logs.filter((log) => log.serverId === serverId);
      }
      getAllLogs() {
        return [...this.logs];
      }
      clear(serverId) {
        if (serverId) {
          this.logs = this.logs.filter((log) => log.serverId !== serverId);
        } else {
          this.logs = [];
        }
      }
    };
    rpcLogStore = new RpcLogStore();
    __name(getRpcLogs, "getRpcLogs");
    __name(getAllRpcLogs, "getAllRpcLogs");
    __name(subscribeToRpcLogs, "subscribeToRpcLogs");
    __name(clearRpcLogs, "clearRpcLogs");
    __name(wrapTransportForLogging, "wrapTransportForLogging");
  }
});

// index.ts
var index_exports = {};
__export(index_exports, {
  AcquireActiveMCPServerTool: () => AcquireActiveMCPServerTool,
  AddMCPServerFromConfigTool: () => AddMCPServerFromConfigTool,
  BaseAdapter: () => BaseAdapter,
  BaseCodeExecutor: () => BaseCodeExecutor,
  BaseConnector: () => BaseConnector,
  BrowserOAuthClientProvider: () => BrowserOAuthClientProvider,
  BrowserTelemetry: () => Tel,
  ConnectMCPServerTool: () => ConnectMCPServerTool,
  E2BCodeExecutor: () => E2BCodeExecutor,
  ElicitationDeclinedError: () => ElicitationDeclinedError,
  ElicitationTimeoutError: () => ElicitationTimeoutError,
  ElicitationValidationError: () => ElicitationValidationError,
  ErrorBoundary: () => ErrorBoundary,
  HttpConnector: () => HttpConnector,
  Image: () => Image,
  ListMCPServersTool: () => ListMCPServersTool,
  LocalStorageProvider: () => LocalStorageProvider,
  Logger: () => Logger,
  MCPAgent: () => MCPAgent,
  MCPClient: () => MCPClient,
  MCPSession: () => MCPSession,
  McpClientProvider: () => McpClientProvider,
  McpUseProvider: () => McpUseProvider,
  MemoryStorageProvider: () => MemoryStorageProvider,
  ObservabilityManager: () => ObservabilityManager,
  PROMPTS: () => PROMPTS,
  ReleaseMCPServerConnectionTool: () => ReleaseMCPServerConnectionTool,
  RemoteAgent: () => RemoteAgent,
  ServerManager: () => ServerManager,
  StdioConnector: () => StdioConnector,
  Tel: () => Tel,
  Telemetry: () => Telemetry,
  ThemeProvider: () => ThemeProvider,
  VERSION: () => VERSION,
  VMCodeExecutor: () => VMCodeExecutor,
  WidgetControls: () => WidgetControls,
  applyProxyConfig: () => applyProxyConfig,
  clearRpcLogs: () => clearRpcLogs,
  createLLMFromString: () => createLLMFromString,
  createReadableStreamFromGenerator: () => createReadableStreamFromGenerator,
  detectFavicon: () => detectFavicon,
  getAllRpcLogs: () => getAllRpcLogs,
  getPackageVersion: () => getPackageVersion,
  getRpcLogs: () => getRpcLogs,
  getSupportedProviders: () => getSupportedProviders,
  isLocalServer: () => isLocalServer,
  isVMAvailable: () => isVMAvailable,
  isValidLLMString: () => isValidLLMString,
  loadConfigFile: () => loadConfigFile,
  logger: () => logger,
  onMcpAuthorization: () => onMcpAuthorization,
  parseLLMString: () => parseLLMString,
  setBrowserTelemetrySource: () => setTelemetrySource,
  setTelemetrySource: () => setTelemetrySource,
  streamEventsToAISDK: () => streamEventsToAISDK,
  streamEventsToAISDKWithTools: () => streamEventsToAISDKWithTools,
  subscribeToRpcLogs: () => subscribeToRpcLogs,
  useMcp: () => useMcp,
  useMcpClient: () => useMcpClient,
  useMcpServer: () => useMcpServer,
  useWidget: () => useWidget,
  useWidgetProps: () => useWidgetProps,
  useWidgetState: () => useWidgetState,
  useWidgetTheme: () => useWidgetTheme
});
module.exports = __toCommonJS(index_exports);

// src/agents/mcp_agent.ts
var import_langchain2 = require("langchain");
var import_zod9 = require("zod");

// src/utils/json-schema-to-zod/JSONSchemaToZod.ts
var import_zod = require("zod");
var JSONSchemaToZod = class {
  static {
    __name(this, "JSONSchemaToZod");
  }
  /**
   * Converts a JSON schema to a Zod schema.
   *
   * @param {JSONSchema} schema - The JSON schema.
   * @returns {ZodSchema} - The Zod schema.
   */
  static convert(schema) {
    return this.parseSchema(schema);
  }
  /**
   * Checks if data matches a condition schema.
   *
   * @param {JSONValue} data - The data to check.
   * @param {JSONSchema} condition - The condition schema.
   * @returns {boolean} - Whether the data matches the condition.
   */
  static matchesCondition(data, condition) {
    if (!condition.properties) {
      return true;
    }
    if (typeof data !== "object" || data === null || Array.isArray(data)) {
      return false;
    }
    const objectData = data;
    for (const [key, propCondition] of Object.entries(condition.properties)) {
      if (!(key in objectData)) {
        if ("const" in propCondition) {
          return false;
        }
        continue;
      }
      const value = objectData[key];
      if ("const" in propCondition && value !== propCondition["const"]) {
        return false;
      }
      if ("minimum" in propCondition && typeof value === "number" && value < propCondition["minimum"]) {
        return false;
      }
      if ("maximum" in propCondition && typeof value === "number" && value > propCondition["maximum"]) {
        return false;
      }
    }
    return true;
  }
  /**
   * Validates data against a conditional schema and adds issues to context if validation fails.
   *
   * @param {JSONValue} data - The data to validate.
   * @param {JSONSchema} schema - The conditional schema.
   * @param {z.RefinementCtx} ctx - The Zod refinement context.
   */
  static validateConditionalSchema(data, schema, ctx) {
    this.validateRequiredProperties(data, schema, ctx);
    this.validatePropertyPatterns(data, schema, ctx);
    this.validateNestedConditions(data, schema, ctx);
  }
  /**
   * Validates that all required properties are present in the data.
   *
   * @param {JSONValue} data - The data to validate.
   * @param {JSONSchema} schema - The schema containing required properties.
   * @param {z.RefinementCtx} ctx - The Zod refinement context.
   */
  static validateRequiredProperties(data, schema, ctx) {
    if (!schema.required) {
      return;
    }
    if (typeof data !== "object" || data === null) {
      for (const requiredProp of schema.required) {
        ctx.addIssue({
          code: import_zod.z.ZodIssueCode.custom,
          message: `Required property '${requiredProp}' is missing`,
          path: [requiredProp]
        });
      }
      return;
    }
    for (const requiredProp of schema.required) {
      if (!(requiredProp in data)) {
        ctx.addIssue({
          code: import_zod.z.ZodIssueCode.custom,
          message: `Required property '${requiredProp}' is missing`,
          path: [requiredProp]
        });
      }
    }
  }
  /**
   * Validates property patterns for string properties.
   *
   * @param {JSONValue} data - The data to validate.
   * @param {JSONSchema} schema - The schema containing property patterns.
   * @param {z.RefinementCtx} ctx - The Zod refinement context.
   */
  static validatePropertyPatterns(data, schema, ctx) {
    if (!schema.properties) {
      return;
    }
    if (typeof data !== "object" || data === null) {
      return;
    }
    if (Array.isArray(data)) {
      return;
    }
    const objectData = data;
    for (const [key, propSchema] of Object.entries(schema.properties)) {
      if (!(key in objectData)) {
        continue;
      }
      const value = objectData[key];
      if (propSchema["pattern"] && typeof value === "string") {
        const regex = new RegExp(propSchema["pattern"]);
        if (!regex.test(value)) {
          ctx.addIssue({
            code: import_zod.z.ZodIssueCode.custom,
            message: `String '${value}' does not match pattern '${propSchema["pattern"]}'`,
            path: [key]
          });
        }
      }
    }
  }
  /**
   * Validates nested if-then-else conditions.
   *
   * @param {JSONValue} data - The data to validate.
   * @param {JSONSchema} schema - The schema containing if-then-else conditions.
   * @param {z.RefinementCtx} ctx - The Zod refinement context.
   */
  static validateNestedConditions(data, schema, ctx) {
    if (!schema["if"] || !schema["then"]) {
      return;
    }
    const matchesIf = this.matchesCondition(data, schema["if"]);
    if (matchesIf) {
      this.validateConditionalSchema(data, schema["then"], ctx);
    } else if (schema["else"]) {
      this.validateConditionalSchema(data, schema["else"], ctx);
    }
  }
  /**
   * Parses a JSON schema and returns the corresponding Zod schema.
   * This is the main entry point for schema conversion.
   *
   * @param {JSONSchema} schema - The JSON schema.
   * @returns {ZodTypeAny} - The ZodTypeAny schema.
   */
  static parseSchema(schema) {
    if (Array.isArray(schema.type)) {
      return this.handleTypeArray(schema);
    }
    if (schema.oneOf || schema.anyOf || schema.allOf) {
      return this.parseCombinator(schema);
    }
    if (schema["if"] && schema["then"]) {
      return this.parseObject(schema);
    }
    if (schema.properties && (!schema.type || schema.type === "object")) {
      return this.parseObject(schema);
    }
    return this.handleSingleType(schema);
  }
  /**
   * Handles schemas with an array of types.
   *
   * @param {JSONSchema} schema - The JSON schema with type array.
   * @returns {ZodTypeAny} - The ZodTypeAny schema.
   */
  static handleTypeArray(schema) {
    if (!Array.isArray(schema.type)) {
      throw new Error("Expected schema.type to be an array");
    }
    if (schema.type.includes("null")) {
      return this.handleNullableType(schema);
    }
    return this.createUnionFromTypes(schema.type, schema);
  }
  /**
   * Handles nullable types by creating a nullable schema.
   *
   * @param {JSONSchema} schema - The JSON schema with nullable type.
   * @returns {ZodTypeAny} - The nullable Zod schema.
   */
  static handleNullableType(schema) {
    if (!Array.isArray(schema.type)) {
      throw new Error("Expected schema.type to be an array");
    }
    const nonNullSchema = { ...schema };
    nonNullSchema.type = schema.type.filter((t) => t !== "null");
    if (nonNullSchema.type.length === 1) {
      const singleTypeSchema = this.handleSingleType({
        ...schema,
        type: nonNullSchema.type[0]
      });
      return singleTypeSchema.nullable();
    }
    const unionSchema = this.parseSchema(nonNullSchema);
    return unionSchema.nullable();
  }
  /**
   * Creates a union type from an array of types.
   *
   * @param {string[]} types - Array of type strings.
   * @param {JSONSchema} baseSchema - The base schema to apply to each type.
   * @returns {ZodTypeAny} - The union Zod schema.
   */
  static createUnionFromTypes(types, baseSchema) {
    const schemas = types.map((type) => {
      const singleTypeSchema = { ...baseSchema, type };
      return this.parseSchema(singleTypeSchema);
    });
    return import_zod.z.union(schemas);
  }
  /**
   * Handles schemas with a single type.
   *
   * @param {JSONSchema} schema - The JSON schema with single type.
   * @returns {ZodTypeAny} - The ZodTypeAny schema.
   */
  static handleSingleType(schema) {
    if (schema.type === void 0) {
      if (schema.oneOf || schema.anyOf || schema.allOf) {
        return this.parseCombinator(schema);
      }
      if (schema.properties) {
        return this.parseObject(schema);
      }
      return import_zod.z.any();
    }
    switch (schema.type) {
      case "string":
        return this.parseString(schema);
      case "number":
      case "integer":
        return this.parseNumberSchema(schema);
      case "boolean":
        return import_zod.z.boolean();
      case "array":
        return this.parseArray(schema);
      case "object":
        return this.parseObject(schema);
      default:
        throw new Error("Unsupported schema type");
    }
  }
  /**
   * Parses a number schema.
   *
   * @param {JSONSchema} schema - The JSON schema for a number.
   * @returns {ZodTypeAny} - The ZodTypeAny schema.
   */
  static parseNumberSchema(schema) {
    const numberSchema = import_zod.z.number();
    let result = numberSchema;
    result = this.applyNumberBounds(numberSchema, schema);
    result = this.applyNumberMultipleOf(numberSchema, schema);
    result = this.applyNumberEnum(numberSchema, schema);
    result = this.applyIntegerConstraint(numberSchema, schema);
    return result;
  }
  /**
   * Applies bounds validation to a number schema.
   *
   * @param {z.ZodNumber} numberSchema - The base number schema.
   * @param {JSONSchema} schema - The JSON schema with bounds.
   * @returns {z.ZodNumber} - The updated schema with bounds validation.
   */
  static applyNumberBounds(numberSchema, schema) {
    let result = numberSchema;
    if (schema["minimum"] !== void 0) {
      result = schema["exclusiveMinimum"] ? result.gt(schema["minimum"]) : result.gte(schema["minimum"]);
    }
    if (schema["maximum"] !== void 0) {
      result = schema["exclusiveMaximum"] ? result.lt(schema["maximum"]) : result.lte(schema["maximum"]);
    }
    return result;
  }
  /**
   * Applies multipleOf validation to a number schema.
   *
   * @param {z.ZodNumber} numberSchema - The base number schema.
   * @param {JSONSchema} schema - The JSON schema with multipleOf.
   * @returns {z.ZodNumber} - The updated schema with multipleOf validation.
   */
  static applyNumberMultipleOf(numberSchema, schema) {
    if (schema["multipleOf"] === void 0) {
      return numberSchema;
    }
    return numberSchema.refine((val) => val % schema["multipleOf"] === 0, {
      message: `Number must be a multiple of ${schema["multipleOf"]}`
    });
  }
  /**
   * Applies enum validation to a number schema.
   *
   * @param {z.ZodNumber} numberSchema - The base number schema.
   * @param {JSONSchema} schema - The JSON schema with enum.
   * @returns {z.ZodNumber} - The updated schema with enum validation.
   */
  static applyNumberEnum(numberSchema, schema) {
    if (!schema.enum) {
      return numberSchema;
    }
    const numberEnums = schema.enum.filter(
      (val) => typeof val === "number"
    );
    if (numberEnums.length === 0) {
      return numberSchema;
    }
    return numberSchema.refine((val) => numberEnums.includes(val), {
      message: `Number must be one of: ${numberEnums.join(", ")}`
    });
  }
  /**
   * Applies integer constraint to a number schema if needed.
   *
   * @param {z.ZodNumber} numberSchema - The base number schema.
   * @param {JSONSchema} schema - The JSON schema.
   * @returns {z.ZodNumber} - The updated schema with integer validation if needed.
   */
  static applyIntegerConstraint(numberSchema, schema) {
    if (schema.type !== "integer") {
      return numberSchema;
    }
    return numberSchema.refine((val) => Number.isInteger(val), {
      message: "Number must be an integer"
    });
  }
  /**
   * Parses a string schema.
   *
   * @param {JSONSchema} schema - The JSON schema for a string.
   * @returns {ZodTypeAny} - The ZodTypeAny schema.
   */
  static parseString(schema) {
    const stringSchema = import_zod.z.string();
    let result = stringSchema;
    if (schema.format) {
      return this.applyStringFormat(stringSchema, schema);
    } else {
      result = this.applyStringPattern(stringSchema, schema);
      result = this.applyStringLength(stringSchema, schema);
      result = this.applyStringEnum(stringSchema, schema);
    }
    return result;
  }
  /**
   * Applies format validation to a string schema.
   *
   * @param {z.ZodString} stringSchema - The base string schema.
   * @param {JSONSchema} schema - The JSON schema with format.
   * @returns {ZodTypeAny} - The updated schema with format validation.
   */
  static applyStringFormat(stringSchema, schema) {
    if (!schema.format) {
      return stringSchema;
    }
    switch (schema.format) {
      case "email":
        return stringSchema.email();
      case "date-time":
        return stringSchema.datetime();
      case "uri":
        return stringSchema.url();
      case "uuid":
        return stringSchema.uuid();
      case "date":
        return stringSchema.date();
      default:
        return stringSchema;
    }
  }
  /**
   * Applies pattern validation to a string schema.
   *
   * @param {z.ZodString} stringSchema - The base string schema.
   * @param {JSONSchema} schema - The JSON schema with pattern.
   * @returns {z.ZodString} - The updated schema with pattern validation.
   */
  static applyStringPattern(stringSchema, schema) {
    if (!schema["pattern"]) {
      return stringSchema;
    }
    const regex = new RegExp(schema["pattern"]);
    return stringSchema.regex(regex, {
      message: `String must match pattern: ${schema["pattern"]}`
    });
  }
  /**
   * Applies length constraints to a string schema.
   *
   * @param {z.ZodString} stringSchema - The base string schema.
   * @param {JSONSchema} schema - The JSON schema with length constraints.
   * @returns {z.ZodString} - The updated schema with length validation.
   */
  static applyStringLength(stringSchema, schema) {
    const result = stringSchema;
    if (schema["minLength"] !== void 0) {
      stringSchema = stringSchema.min(schema["minLength"]);
    }
    if (schema["maxLength"] !== void 0) {
      stringSchema = stringSchema.max(schema["maxLength"]);
    }
    return result;
  }
  /**
   * Applies enum validation to a string schema.
   *
   * @param {z.ZodString} stringSchema - The base string schema.
   * @param {JSONSchema} schema - The JSON schema with enum.
   * @returns {ZodTypeAny} - The updated schema with enum validation.
   */
  static applyStringEnum(stringSchema, schema) {
    if (!schema.enum) {
      return stringSchema;
    }
    return stringSchema.refine((val) => schema.enum?.includes(val), {
      message: `Value must be one of: ${schema.enum?.join(", ")}`
    });
  }
  /**
   * Parses a JSON schema of type array and returns the corresponding Zod schema.
   *
   * @param {JSONSchema} schema - The JSON schema.
   * @returns {ZodTypeAny} - The ZodTypeAny schema.
   */
  static parseArray(schema) {
    if (Array.isArray(schema.items)) {
      const tupleSchemas = schema.items.map((item) => this.parseSchema(item));
      return import_zod.z.union(tupleSchemas);
    }
    const itemSchema = schema.items ? this.parseSchema(schema.items) : import_zod.z.any();
    const arraySchema = import_zod.z.array(itemSchema);
    let result = arraySchema;
    result = this.applyArrayConstraints(arraySchema, schema);
    return result;
  }
  /**
   * Applies constraints to an array schema.
   *
   * @param {z.ZodArray<any>} arraySchema - The base array schema.
   * @param {JSONSchema} schema - The JSON schema with array constraints.
   * @returns {z.ZodTypeAny} - The updated array schema with constraints.
   */
  static applyArrayConstraints(arraySchema, schema) {
    if (schema["minItems"] !== void 0) {
      arraySchema = arraySchema.min(schema["minItems"]);
    }
    if (schema["maxItems"] !== void 0) {
      arraySchema = arraySchema.max(schema["maxItems"]);
    }
    if (schema["uniqueItems"]) {
      return arraySchema.refine(
        (items) => new Set(items).size === items.length,
        { message: "Array items must be unique" }
      );
    }
    return arraySchema;
  }
  /**
   * Parses an object schema.
   *
   * @param {JSONSchema} schema - The JSON schema for an object.
   * @returns {ZodTypeAny} - The ZodTypeAny schema.
   */
  static parseObject(schema) {
    if (schema["if"] && schema["then"]) {
      return this.parseConditional(schema);
    }
    const shape = {};
    this.processObjectProperties(schema, shape);
    return this.processAdditionalProperties(schema, import_zod.z.object(shape));
  }
  /**
   * Processes object properties and builds the shape object.
   *
   * @param {JSONSchema} schema - The JSON schema for an object.
   * @param {Record<string, ZodTypeAny>} shape - The shape object to populate.
   */
  static processObjectProperties(schema, shape) {
    const required = new Set(schema.required || []);
    if (!schema.properties) {
      return;
    }
    for (const [key, propSchema] of Object.entries(schema.properties)) {
      const zodSchema = this.parseSchema(propSchema);
      shape[key] = required.has(key) ? zodSchema : zodSchema.optional();
    }
  }
  /**
   * Processes additionalProperties configuration.
   *
   * @param {JSONSchema} schema - The JSON schema for an object.
   * @param {z.ZodObject<any, any>} objectSchema - The Zod object schema.
   * @returns {z.ZodObject<any, any>} - The updated Zod object schema.
   */
  static processAdditionalProperties(schema, objectSchema) {
    if (schema.additionalProperties === true) {
      return objectSchema.passthrough();
    } else if (schema.additionalProperties && typeof schema.additionalProperties === "object") {
      const additionalPropSchema = this.parseSchema(
        schema.additionalProperties
      );
      return objectSchema.catchall(additionalPropSchema);
    } else {
      return objectSchema.strict();
    }
  }
  /**
   * Parses a conditional schema with if-then-else.
   *
   * @param {JSONSchema} schema - The JSON schema with conditional validation.
   * @returns {ZodTypeAny} - The conditional Zod schema.
   */
  static parseConditional(schema) {
    const zodObject = this.createBaseObjectSchema(schema);
    const ifCondition = schema["if"];
    const thenSchema = schema["then"];
    const elseSchema = schema["else"];
    return zodObject.superRefine((data, ctx) => {
      const dataWithDefaults = this.applyDefaultValues(
        data,
        schema
      );
      if (this.matchesCondition(dataWithDefaults, ifCondition)) {
        this.validateConditionalSchema(dataWithDefaults, thenSchema, ctx);
      } else if (elseSchema) {
        this.validateConditionalSchema(dataWithDefaults, elseSchema, ctx);
      }
    });
  }
  /**
   * Creates a base object schema from the given JSON schema.
   *
   * @param {JSONSchema} schema - The JSON schema.
   * @returns {z.ZodObject<any, any>} - The base Zod object schema.
   */
  static createBaseObjectSchema(schema) {
    const shape = {};
    const required = new Set(schema.required || []);
    for (const [key, value] of Object.entries(schema.properties || {})) {
      const zodSchema = this.parseSchema(value);
      shape[key] = required.has(key) ? zodSchema : zodSchema.optional();
    }
    const zodObject = import_zod.z.object(shape);
    return this.processAdditionalProperties(schema, zodObject);
  }
  /**
   * Applies default values from schema properties to data object.
   *
   * @param {JSONValue} data - The original data object.
   * @param {JSONSchema} schema - The schema with default values.
   * @returns {JSONValue} - The data object with defaults applied.
   */
  static applyDefaultValues(data, schema) {
    if (typeof data !== "object" || data === null) {
      return data;
    }
    if (Array.isArray(data)) {
      return data;
    }
    const objectData = data;
    const dataWithDefaults = { ...objectData };
    if (!schema.properties) {
      return dataWithDefaults;
    }
    for (const [key, propSchema] of Object.entries(schema.properties)) {
      if (!(key in dataWithDefaults) && "default" in propSchema) {
        dataWithDefaults[key] = propSchema["default"];
      }
    }
    return dataWithDefaults;
  }
  /**
   * Parses a schema with combinators (oneOf, anyOf, allOf).
   * Delegates to the appropriate combinator parser based on which combinator is present.
   *
   * @param {JSONSchema} schema - The JSON schema with combinators.
   * @returns {ZodTypeAny} - The ZodTypeAny schema.
   */
  static parseCombinator(schema) {
    if (schema.oneOf) {
      return this.parseOneOf(schema.oneOf);
    }
    if (schema.anyOf) {
      return this.parseAnyOf(schema.anyOf);
    }
    if (schema.allOf) {
      return this.parseAllOf(schema.allOf);
    }
    throw new Error("Unsupported schema type");
  }
  /**
   * Parses a oneOf combinator schema.
   *
   * @param {JSONSchema[]} schemas - Array of JSON schemas in the oneOf.
   * @returns {ZodTypeAny} - The ZodTypeAny schema.
   */
  static parseOneOf(schemas) {
    return this.createUnionFromSchemas(schemas);
  }
  /**
   * Parses an anyOf combinator schema.
   *
   * @param {JSONSchema[]} schemas - Array of JSON schemas in the anyOf.
   * @returns {ZodTypeAny} - The ZodTypeAny schema.
   */
  static parseAnyOf(schemas) {
    return this.createUnionFromSchemas(schemas);
  }
  /**
   * Creates a union from an array of schemas, handling special cases.
   *
   * @param {JSONSchema[]} schemas - Array of JSON schemas to create a union from.
   * @returns {ZodTypeAny} - The union Zod schema.
   */
  static createUnionFromSchemas(schemas) {
    if (schemas.length === 0) {
      return import_zod.z.any();
    }
    if (schemas.length === 1) {
      return this.parseSchema(schemas[0]);
    }
    const zodSchemas = [];
    for (const subSchema of schemas) {
      if (subSchema.type === "null") {
        zodSchemas.push(import_zod.z.null());
      } else {
        zodSchemas.push(this.parseSchema(subSchema));
      }
    }
    if (zodSchemas.length >= 2) {
      return import_zod.z.union(zodSchemas);
    } else if (zodSchemas.length === 1) {
      return zodSchemas[0];
    }
    return import_zod.z.any();
  }
  /**
   * Parses an allOf combinator schema by merging all schemas.
   *
   * @param {JSONSchema[]} schemas - Array of JSON schemas in the allOf.
   * @returns {ZodTypeAny} - The ZodTypeAny schema.
   */
  static parseAllOf(schemas) {
    if (schemas.length === 0) {
      return import_zod.z.any();
    }
    if (schemas.length === 1) {
      return this.parseSchema(schemas[0]);
    }
    const mergedSchema = schemas.reduce(
      (acc, currentSchema) => this.mergeSchemas(acc, currentSchema)
    );
    return this.parseSchema(mergedSchema);
  }
  /**
   * Merges two JSON schemas together.
   *
   * @param {JSONSchema} baseSchema - The base JSON schema.
   * @param {JSONSchema} addSchema - The JSON schema to add.
   * @returns {JSONSchema} - The merged JSON schema
   */
  static mergeSchemas(baseSchema, addSchema) {
    const merged = { ...baseSchema, ...addSchema };
    if (baseSchema.properties && addSchema.properties) {
      const mergedProperties = {
        ...baseSchema.properties,
        ...addSchema.properties
      };
      merged.properties = mergedProperties;
    }
    if (baseSchema.required && addSchema.required) {
      const mergedRequired = [
        .../* @__PURE__ */ new Set([...baseSchema.required, ...addSchema.required])
      ];
      merged.required = mergedRequired;
    }
    return merged;
  }
};

// src/adapters/langchain_adapter.ts
var import_tools = require("@langchain/core/tools");
var import_zod2 = require("zod");
init_logging();

// src/adapters/base.ts
init_logging();
var BaseAdapter = class {
  static {
    __name(this, "BaseAdapter");
  }
  /**
   * List of tool names that should not be available.
   */
  disallowedTools;
  /**
   * Internal cache that maps a connector instance to the list of tools
   * generated for it.
   */
  connectorToolMap = /* @__PURE__ */ new Map();
  constructor(disallowedTools) {
    this.disallowedTools = disallowedTools ?? [];
  }
  /**
   * Create tools from an MCPClient instance.
   *
   * This is the recommended way to create tools from an MCPClient, as it handles
   * session creation and connector extraction automatically.
   *
   * @param client          The MCPClient to extract tools from.
   * @param disallowedTools Optional list of tool names to exclude.
   * @returns               A promise that resolves with a list of converted tools.
   */
  static async createTools(client, disallowedTools) {
    const adapter = new this(disallowedTools);
    if (!client.activeSessions || Object.keys(client.activeSessions).length === 0) {
      logger.info("No active sessions found, creating new ones...");
      await client.createAllSessions();
    }
    const sessions = client.getAllActiveSessions();
    const connectors = Object.values(sessions).map(
      (session) => session.connector
    );
    return adapter.createToolsFromConnectors(connectors);
  }
  /**
   * Dynamically load tools for a specific connector.
   *
   * @param connector The connector to load tools for.
   * @returns         The list of tools that were loaded in the target framework's format.
   */
  async loadToolsForConnector(connector) {
    if (this.connectorToolMap.has(connector)) {
      const cached = this.connectorToolMap.get(connector);
      logger.debug(`Returning ${cached.length} existing tools for connector`);
      return cached;
    }
    const connectorTools = [];
    const success = await this.ensureConnectorInitialized(connector);
    if (!success) {
      return [];
    }
    for (const tool of connector.tools) {
      const converted = this.convertTool(tool, connector);
      if (converted) {
        connectorTools.push(converted);
      }
    }
    this.connectorToolMap.set(connector, connectorTools);
    logger.debug(
      `Loaded ${connectorTools.length} new tools for connector: ${connectorTools.map((t) => t?.name ?? String(t)).join(", ")}`
    );
    return connectorTools;
  }
  /**
   * Create tools from MCP tools in all provided connectors.
   *
   * @param connectors List of MCP connectors to create tools from.
   * @returns         A promise that resolves with all converted tools.
   */
  async createToolsFromConnectors(connectors) {
    const tools = [];
    for (const connector of connectors) {
      const connectorTools = await this.loadToolsForConnector(connector);
      tools.push(...connectorTools);
    }
    logger.debug(`Available tools: ${tools.length}`);
    return tools;
  }
  /**
   * Dynamically load resources for a specific connector.
   *
   * @param connector The connector to load resources for.
   * @returns         The list of resources that were loaded in the target framework's format.
   */
  async loadResourcesForConnector(connector) {
    const connectorResources = [];
    const success = await this.ensureConnectorInitialized(connector);
    if (!success) {
      return [];
    }
    try {
      const resourcesResult = await connector.listAllResources();
      const resources = resourcesResult?.resources || [];
      if (this.convertResource) {
        for (const resource of resources) {
          const converted = this.convertResource(resource, connector);
          if (converted) {
            connectorResources.push(converted);
          }
        }
      }
      logger.debug(
        `Loaded ${connectorResources.length} new resources for connector: ${connectorResources.map((r) => r?.name ?? String(r)).join(", ")}`
      );
    } catch (err) {
      logger.warn(`Error loading resources for connector: ${err}`);
    }
    return connectorResources;
  }
  /**
   * Dynamically load prompts for a specific connector.
   *
   * @param connector The connector to load prompts for.
   * @returns         The list of prompts that were loaded in the target framework's format.
   */
  async loadPromptsForConnector(connector) {
    const connectorPrompts = [];
    const success = await this.ensureConnectorInitialized(connector);
    if (!success) {
      return [];
    }
    try {
      const promptsResult = await connector.listPrompts();
      const prompts = promptsResult?.prompts || [];
      if (this.convertPrompt) {
        for (const prompt of prompts) {
          const converted = this.convertPrompt(prompt, connector);
          if (converted) {
            connectorPrompts.push(converted);
          }
        }
      }
      logger.debug(
        `Loaded ${connectorPrompts.length} new prompts for connector: ${connectorPrompts.map((p) => p?.name ?? String(p)).join(", ")}`
      );
    } catch (err) {
      logger.warn(`Error loading prompts for connector: ${err}`);
    }
    return connectorPrompts;
  }
  /**
   * Create resources from MCP resources in all provided connectors.
   *
   * @param connectors List of MCP connectors to create resources from.
   * @returns         A promise that resolves with all converted resources.
   */
  async createResourcesFromConnectors(connectors) {
    const resources = [];
    for (const connector of connectors) {
      const connectorResources = await this.loadResourcesForConnector(connector);
      resources.push(...connectorResources);
    }
    logger.debug(`Available resources: ${resources.length}`);
    return resources;
  }
  /**
   * Create prompts from MCP prompts in all provided connectors.
   *
   * @param connectors List of MCP connectors to create prompts from.
   * @returns         A promise that resolves with all converted prompts.
   */
  async createPromptsFromConnectors(connectors) {
    const prompts = [];
    for (const connector of connectors) {
      const connectorPrompts = await this.loadPromptsForConnector(connector);
      prompts.push(...connectorPrompts);
    }
    logger.debug(`Available prompts: ${prompts.length}`);
    return prompts;
  }
  /**
   * Check if a connector is initialized and has tools.
   *
   * @param connector The connector to check.
   * @returns         True if the connector is initialized and has tools, false otherwise.
   */
  checkConnectorInitialized(connector) {
    return Boolean(connector.tools && connector.tools.length);
  }
  /**
   * Ensure a connector is initialized.
   *
   * @param connector The connector to initialize.
   * @returns         True if initialization succeeded, false otherwise.
   */
  async ensureConnectorInitialized(connector) {
    if (!this.checkConnectorInitialized(connector)) {
      logger.debug("Connector doesn't have tools, initializing it");
      try {
        await connector.initialize();
        return true;
      } catch (err) {
        logger.error(`Error initializing connector: ${err}`);
        return false;
      }
    }
    return true;
  }
};

// src/adapters/langchain_adapter.ts
function schemaToZod(schema) {
  try {
    return JSONSchemaToZod.convert(schema);
  } catch (err) {
    logger.warn(`Failed to convert JSON schema to Zod: ${err}`);
    return import_zod2.z.any();
  }
}
__name(schemaToZod, "schemaToZod");
var LangChainAdapter = class extends BaseAdapter {
  static {
    __name(this, "LangChainAdapter");
  }
  constructor(disallowedTools = []) {
    super(disallowedTools);
  }
  /**
   * Convert a single MCP tool specification into a LangChainJS structured tool.
   */
  convertTool(mcpTool, connector) {
    if (this.disallowedTools.includes(mcpTool.name)) {
      return null;
    }
    const argsSchema = mcpTool.inputSchema ? schemaToZod(mcpTool.inputSchema) : import_zod2.z.object({}).optional();
    const tool = new import_tools.DynamicStructuredTool({
      name: mcpTool.name ?? "NO NAME",
      description: mcpTool.description ?? "",
      // Blank is acceptable but discouraged.
      schema: argsSchema,
      func: /* @__PURE__ */ __name(async (input) => {
        logger.debug(
          `MCP tool "${mcpTool.name}" received input: ${JSON.stringify(input)}`
        );
        try {
          const result = await connector.callTool(
            mcpTool.name,
            input
          );
          return JSON.stringify(result);
        } catch (err) {
          logger.error(`Error executing MCP tool: ${err.message}`);
          return `Error executing MCP tool: ${String(err)}`;
        }
      }, "func")
    });
    return tool;
  }
  /**
   * Convert a single MCP resource into a LangChainJS structured tool.
   * Each resource becomes an async tool that returns its content when called.
   */
  convertResource(mcpResource, connector) {
    const sanitizeName = /* @__PURE__ */ __name((name) => {
      return name.replace(/[^A-Za-z0-9_]+/g, "_").toLowerCase().replace(/^_+|_+$/g, "");
    }, "sanitizeName");
    const resourceName = sanitizeName(
      mcpResource.name || `resource_${mcpResource.uri}`
    );
    const resourceUri = mcpResource.uri;
    const tool = new import_tools.DynamicStructuredTool({
      name: resourceName,
      description: mcpResource.description || `Return the content of the resource located at URI ${resourceUri}.`,
      schema: import_zod2.z.object({}).optional(),
      // Resources take no arguments
      func: /* @__PURE__ */ __name(async () => {
        logger.debug(`Resource tool: "${resourceName}" called`);
        try {
          const result = await connector.readResource(resourceUri);
          if (result.contents && result.contents.length > 0) {
            return result.contents.map((content) => {
              if (typeof content === "string") {
                return content;
              }
              if (content.text) {
                return content.text;
              }
              if (content.uri) {
                return content.uri;
              }
              return JSON.stringify(content);
            }).join("\n");
          }
          return "Resource is empty or unavailable";
        } catch (err) {
          logger.error(`Error reading resource: ${err.message}`);
          return `Error reading resource: ${String(err)}`;
        }
      }, "func")
    });
    return tool;
  }
  /**
   * Convert a single MCP prompt into a LangChainJS structured tool.
   * The resulting tool executes getPrompt on the connector with the prompt's name
   * and the user-provided arguments (if any).
   */
  convertPrompt(mcpPrompt, connector) {
    let argsSchema = import_zod2.z.object({}).optional();
    if (mcpPrompt.arguments && mcpPrompt.arguments.length > 0) {
      const schemaFields = {};
      for (const arg of mcpPrompt.arguments) {
        const zodType = import_zod2.z.string();
        if (arg.required !== false) {
          schemaFields[arg.name] = zodType;
        } else {
          schemaFields[arg.name] = zodType.optional();
        }
      }
      argsSchema = Object.keys(schemaFields).length > 0 ? import_zod2.z.object(schemaFields) : import_zod2.z.object({}).optional();
    }
    const tool = new import_tools.DynamicStructuredTool({
      name: mcpPrompt.name,
      description: mcpPrompt.description || "",
      schema: argsSchema,
      func: /* @__PURE__ */ __name(async (input) => {
        logger.debug(
          `Prompt tool: "${mcpPrompt.name}" called with args: ${JSON.stringify(input)}`
        );
        try {
          const result = await connector.getPrompt(mcpPrompt.name, input);
          if (result.messages && result.messages.length > 0) {
            return result.messages.map((msg) => {
              if (typeof msg === "string") {
                return msg;
              }
              if (msg.content) {
                return typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content);
              }
              return JSON.stringify(msg);
            }).join("\n");
          }
          return "Prompt returned no messages";
        } catch (err) {
          logger.error(`Error getting prompt: ${err.message}`);
          return `Error getting prompt: ${String(err)}`;
        }
      }, "func")
    });
    return tool;
  }
};

// src/agents/mcp_agent.ts
init_logging();

// src/managers/server_manager.ts
init_logging();

// src/managers/tools/acquire_active_mcp_server.ts
var import_zod3 = require("zod");

// src/managers/tools/base.ts
var import_tools2 = require("@langchain/core/tools");
var MCPServerTool = class extends import_tools2.StructuredTool {
  static {
    __name(this, "MCPServerTool");
  }
  name = "mcp_server_tool";
  description = "Base tool for MCP server operations.";
  schema;
  _manager;
  constructor(manager) {
    super();
    this._manager = manager;
  }
  async _call(_arg, _runManager, _parentConfig) {
    throw new Error("Method not implemented.");
  }
  get manager() {
    return this._manager;
  }
};

// src/managers/tools/acquire_active_mcp_server.ts
var PresentActiveServerSchema = import_zod3.z.object({});
var AcquireActiveMCPServerTool = class extends MCPServerTool {
  static {
    __name(this, "AcquireActiveMCPServerTool");
  }
  name = "get_active_mcp_server";
  description = "Get the currently active MCP (Model Context Protocol) server";
  schema = PresentActiveServerSchema;
  constructor(manager) {
    super(manager);
  }
  async _call() {
    if (!this.manager.activeServer) {
      return `No MCP server is currently active. Use connect_to_mcp_server to connect to a server.`;
    }
    return `Currently active MCP server: ${this.manager.activeServer}`;
  }
};

// src/managers/tools/add_server_from_config.ts
var import_tools3 = require("@langchain/core/tools");
var import_zod4 = require("zod");
init_logging();
var AddMCPServerFromConfigTool = class extends import_tools3.StructuredTool {
  static {
    __name(this, "AddMCPServerFromConfigTool");
  }
  name = "add_mcp_server_from_config";
  description = "Adds a new MCP server to the client from a configuration object and connects to it, making its tools available.";
  schema = import_zod4.z.object({
    serverName: import_zod4.z.string().describe("The name for the new MCP server."),
    serverConfig: import_zod4.z.any().describe(
      'The configuration object for the server. This should not include the top-level "mcpServers" key.'
    )
  });
  manager;
  constructor(manager) {
    super();
    this.manager = manager;
  }
  async _call({
    serverName,
    serverConfig
  }) {
    try {
      this.manager.client.addServer(serverName, serverConfig);
      let result = `Server '${serverName}' added to the client.`;
      logger.debug(
        `Connecting to new server '${serverName}' and discovering tools.`
      );
      const session = await this.manager.client.createSession(serverName);
      const connector = session.connector;
      const tools = await this.manager.adapter.createToolsFromConnectors([connector]);
      this.manager.serverTools[serverName] = tools;
      this.manager.initializedServers[serverName] = true;
      this.manager.activeServer = serverName;
      const numTools = tools.length;
      result += ` Session created and connected. '${serverName}' is now the active server with ${numTools} tools available.`;
      result += `

${tools.map((t) => t.name).join("\n")}`;
      logger.info(result);
      return result;
    } catch (e) {
      logger.error(
        `Failed to add or connect to server '${serverName}': ${e.message}`
      );
      return `Failed to add or connect to server '${serverName}': ${e.message}`;
    }
  }
};

// src/managers/tools/connect_mcp_server.ts
var import_zod5 = require("zod");
init_logging();
var ConnectMCPServerSchema = import_zod5.z.object({
  serverName: import_zod5.z.string().describe("The name of the MCP server.")
});
var ConnectMCPServerTool = class extends MCPServerTool {
  static {
    __name(this, "ConnectMCPServerTool");
  }
  name = "connect_to_mcp_server";
  description = "Connect to a specific MCP (Model Context Protocol) server to use its tools. Use this tool to connect to a specific server and use its tools.";
  schema = ConnectMCPServerSchema;
  constructor(manager) {
    super(manager);
  }
  async _call({ serverName }) {
    const serverNames = this.manager.client.getServerNames();
    if (!serverNames.includes(serverName)) {
      const available = serverNames.length > 0 ? serverNames.join(", ") : "none";
      return `Server '${serverName}' not found. Available servers: ${available}`;
    }
    if (this.manager.activeServer === serverName) {
      return `Already connected to MCP server '${serverName}'`;
    }
    try {
      let session = this.manager.client.getSession(serverName);
      logger.debug(`Using existing session for server '${serverName}'`);
      if (!session) {
        logger.debug(`Creating new session for server '${serverName}'`);
        session = await this.manager.client.createSession(serverName);
      }
      this.manager.activeServer = serverName;
      if (!this.manager.serverTools[serverName]) {
        const connector = session.connector;
        const tools = await this.manager.adapter.createToolsFromConnectors([connector]);
        const resources = await this.manager.adapter.createResourcesFromConnectors([connector]);
        const prompts = await this.manager.adapter.createPromptsFromConnectors([connector]);
        const allItems = [...tools, ...resources, ...prompts];
        this.manager.serverTools[serverName] = allItems;
        this.manager.initializedServers[serverName] = true;
        logger.debug(
          `Loaded ${allItems.length} items for server '${serverName}': ${tools.length} tools, ${resources.length} resources, ${prompts.length} prompts`
        );
      }
      const serverTools = this.manager.serverTools[serverName] || [];
      const numTools = serverTools.length;
      return `Connected to MCP server '${serverName}'. ${numTools} tools, resources, and prompts are now available.`;
    } catch (error) {
      logger.error(
        `Error connecting to server '${serverName}': ${String(error)}`
      );
      return `Failed to connect to server '${serverName}': ${String(error)}`;
    }
  }
};

// src/managers/tools/list_mcp_servers.ts
var import_zod6 = require("zod");
init_logging();
var EnumerateServersSchema = import_zod6.z.object({});
var ListMCPServersTool = class extends MCPServerTool {
  static {
    __name(this, "ListMCPServersTool");
  }
  name = "list_mcp_servers";
  description = `Lists all available MCP (Model Context Protocol) servers that can be connected to, along with the tools available on each server. Use this tool to discover servers and see what functionalities they offer.`;
  schema = EnumerateServersSchema;
  constructor(manager) {
    super(manager);
  }
  async _call() {
    const serverNames = this.manager.client.getServerNames();
    if (serverNames.length === 0) {
      return `No MCP servers are currently defined.`;
    }
    const outputLines = ["Available MCP servers:"];
    for (const serverName of serverNames) {
      const isActiveServer = serverName === this.manager.activeServer;
      const activeFlag = isActiveServer ? " (ACTIVE)" : "";
      outputLines.push(`- ${serverName}${activeFlag}`);
      try {
        const serverTools = this.manager.serverTools?.[serverName] ?? [];
        const numberOfTools = Array.isArray(serverTools) ? serverTools.length : 0;
        outputLines.push(`${numberOfTools} tools available for this server
`);
      } catch (error) {
        logger.error(
          `Unexpected error listing tools for server '${serverName}': ${String(error)}`
        );
      }
    }
    return outputLines.join("\n");
  }
};

// src/managers/tools/release_mcp_server_connection.ts
var import_zod7 = require("zod");
var ReleaseConnectionSchema = import_zod7.z.object({});
var ReleaseMCPServerConnectionTool = class extends MCPServerTool {
  static {
    __name(this, "ReleaseMCPServerConnectionTool");
  }
  name = "disconnect_from_mcp_server";
  description = "Disconnect from the currently active MCP (Model Context Protocol) server";
  schema = ReleaseConnectionSchema;
  constructor(manager) {
    super(manager);
  }
  async _call() {
    if (!this.manager.activeServer) {
      return `No MCP server is currently active, so there's nothing to disconnect from.`;
    }
    const serverName = this.manager.activeServer;
    this.manager.activeServer = null;
    return `Successfully disconnected from MCP server '${serverName}'.`;
  }
};

// src/managers/server_manager.ts
function isEqual(a, b) {
  if (a === b) return true;
  if (a == null || b == null) return false;
  if (typeof a !== typeof b) return false;
  if (a instanceof Date && b instanceof Date) {
    return a.getTime() === b.getTime();
  }
  if (Array.isArray(a) && Array.isArray(b)) {
    if (a.length !== b.length) return false;
    return a.every((item, index) => isEqual(item, b[index]));
  }
  if (typeof a === "object" && typeof b === "object") {
    const keysA = Object.keys(a);
    const keysB = Object.keys(b);
    if (keysA.length !== keysB.length) return false;
    return keysA.every((key) => {
      return Object.prototype.hasOwnProperty.call(b, key) && isEqual(a[key], b[key]);
    });
  }
  return false;
}
__name(isEqual, "isEqual");
var ServerManager = class {
  static {
    __name(this, "ServerManager");
  }
  initializedServers = {};
  serverTools = {};
  client;
  adapter;
  activeServer = null;
  overrideManagementTools;
  constructor(client, adapter, managementTools) {
    this.client = client;
    this.adapter = adapter;
    this.overrideManagementTools = managementTools;
  }
  setManagementTools(tools) {
    this.overrideManagementTools = tools;
    logger.info(
      `Overriding default management tools with a new set of ${tools.length} tools.`
    );
  }
  logState(context) {
    const allServerNames = this.client.getServerNames();
    const activeSessionNames = Object.keys(this.client.getAllActiveSessions());
    if (allServerNames.length === 0) {
      logger.info("Server Manager State: No servers configured.");
      return;
    }
    const tableData = allServerNames.map((name) => ({
      "Server Name": name,
      Connected: activeSessionNames.includes(name) ? "\u2705" : "\u274C",
      Initialized: this.initializedServers[name] ? "\u2705" : "\u274C",
      "Tool Count": this.serverTools[name]?.length ?? 0,
      Active: this.activeServer === name ? "\u2705" : "\u274C"
    }));
    logger.info(`Server Manager State: [${context}]`);
    console.table(tableData);
  }
  initialize() {
    const serverNames = this.client.getServerNames?.();
    if (serverNames.length === 0) {
      logger.warn("No MCP servers defined in client configuration");
    }
  }
  async prefetchServerTools() {
    const servers = this.client.getServerNames();
    for (const serverName of servers) {
      try {
        let session = null;
        session = this.client.getSession(serverName);
        logger.debug(
          `Using existing session for server '${serverName}' to prefetch tools.`
        );
        if (!session) {
          session = await this.client.createSession(serverName).catch((createSessionError) => {
            logger.warn(
              `Could not create session for '${serverName}' during prefetch: ${createSessionError}`
            );
            return null;
          });
          logger.debug(
            `Temporarily created session for '${serverName}' to prefetch tools.`
          );
        }
        if (session) {
          const connector = session.connector;
          let tools = [];
          let resources = [];
          let prompts = [];
          try {
            tools = await this.adapter.createToolsFromConnectors([connector]);
            resources = await this.adapter.createResourcesFromConnectors([
              connector
            ]);
            prompts = await this.adapter.createPromptsFromConnectors([
              connector
            ]);
          } catch (toolFetchError) {
            logger.error(
              `Failed to create tools/resources/prompts from connector for server '${serverName}': ${toolFetchError}`
            );
            continue;
          }
          const allItems = [...tools, ...resources, ...prompts];
          const cachedTools = this.serverTools[serverName];
          const toolsChanged = !cachedTools || !isEqual(cachedTools, allItems);
          if (toolsChanged) {
            this.serverTools[serverName] = allItems;
            this.initializedServers[serverName] = true;
            logger.debug(
              `Prefetched ${allItems.length} items for server '${serverName}': ${tools.length} tools, ${resources.length} resources, ${prompts.length} prompts.`
            );
          } else {
            logger.debug(
              `Tools for server '${serverName}' unchanged, using cached version.`
            );
          }
        }
      } catch (outerError) {
        logger.error(
          `Error prefetching tools for server '${serverName}': ${outerError}`
        );
      }
    }
  }
  get tools() {
    if (logger.level === "debug") {
      this.logState("Providing tools to agent");
    }
    const managementTools = this.overrideManagementTools ?? [
      new AddMCPServerFromConfigTool(this),
      new ListMCPServersTool(this),
      new ConnectMCPServerTool(this),
      new AcquireActiveMCPServerTool(this),
      new ReleaseMCPServerConnectionTool(this)
    ];
    if (this.activeServer && this.serverTools[this.activeServer]) {
      const activeTools = this.serverTools[this.activeServer];
      logger.debug(
        `Adding ${activeTools.length} tools from active server '${this.activeServer}'`
      );
      return [...managementTools, ...activeTools];
    }
    return managementTools;
  }
};

// src/observability/index.ts
init_langfuse();
init_langfuse();

// src/observability/manager.ts
init_logging();
var ObservabilityManager = class {
  static {
    __name(this, "ObservabilityManager");
  }
  customCallbacks;
  availableHandlers = [];
  handlerNames = [];
  initialized = false;
  verbose;
  observe;
  agentId;
  metadata;
  metadataProvider;
  tagsProvider;
  constructor(config = {}) {
    this.customCallbacks = config.customCallbacks;
    this.verbose = config.verbose ?? false;
    this.observe = config.observe ?? true;
    this.agentId = config.agentId;
    this.metadata = config.metadata;
    this.metadataProvider = config.metadataProvider;
    this.tagsProvider = config.tagsProvider;
  }
  /**
   * Collect all available observability handlers from configured platforms.
   */
  async collectAvailableHandlers() {
    if (this.initialized) {
      return;
    }
    try {
      const { langfuseHandler: langfuseHandler2, langfuseInitPromise: langfuseInitPromise2 } = await Promise.resolve().then(() => (init_langfuse(), langfuse_exports));
      if (this.agentId || this.metadata || this.metadataProvider || this.tagsProvider) {
        const { initializeLangfuse: initializeLangfuse2 } = await Promise.resolve().then(() => (init_langfuse(), langfuse_exports));
        await initializeLangfuse2(
          this.agentId,
          this.metadata,
          this.metadataProvider,
          this.tagsProvider
        );
        logger.debug(
          `ObservabilityManager: Reinitialized Langfuse with agent ID: ${this.agentId}, metadata: ${JSON.stringify(this.metadata)}`
        );
      } else {
        const initPromise = langfuseInitPromise2();
        if (initPromise) {
          await initPromise;
        }
      }
      const handler = langfuseHandler2();
      if (handler) {
        this.availableHandlers.push(handler);
        this.handlerNames.push("Langfuse");
        logger.debug("ObservabilityManager: Langfuse handler available");
      }
    } catch {
      logger.debug("ObservabilityManager: Langfuse module not available");
    }
    this.initialized = true;
  }
  /**
   * Get the list of callbacks to use.
   * @returns List of callbacks - either custom callbacks if provided, or all available observability handlers.
   */
  async getCallbacks() {
    if (!this.observe) {
      logger.debug(
        "ObservabilityManager: Observability disabled via observe=false"
      );
      return [];
    }
    if (this.customCallbacks) {
      logger.debug(
        `ObservabilityManager: Using ${this.customCallbacks.length} custom callbacks`
      );
      return this.customCallbacks;
    }
    await this.collectAvailableHandlers();
    if (this.availableHandlers.length > 0) {
      logger.debug(
        `ObservabilityManager: Using ${this.availableHandlers.length} handlers`
      );
    } else {
      logger.debug("ObservabilityManager: No callbacks configured");
    }
    return this.availableHandlers;
  }
  /**
   * Get the names of available handlers.
   * @returns List of handler names (e.g., ["Langfuse", "Laminar"])
   */
  async getHandlerNames() {
    if (!this.observe) {
      return [];
    }
    if (this.customCallbacks) {
      return this.customCallbacks.map((cb) => cb.constructor.name);
    }
    await this.collectAvailableHandlers();
    return this.handlerNames;
  }
  /**
   * Check if any callbacks are available.
   * @returns True if callbacks are available, False otherwise.
   */
  async hasCallbacks() {
    if (!this.observe) {
      return false;
    }
    const callbacks = await this.getCallbacks();
    return callbacks.length > 0;
  }
  /**
   * Get the current observability status including metadata and tags.
   * @returns Object containing enabled status, callback count, handler names, metadata, and tags.
   */
  async getStatus() {
    const callbacks = await this.getCallbacks();
    const handlerNames = await this.getHandlerNames();
    const currentMetadata = this.metadataProvider ? this.metadataProvider() : this.metadata || {};
    const currentTags = this.tagsProvider ? this.tagsProvider() : [];
    return {
      enabled: this.observe && callbacks.length > 0,
      callbackCount: callbacks.length,
      handlerNames,
      metadata: currentMetadata,
      tags: currentTags
    };
  }
  /**
   * Add a callback to the custom callbacks list.
   * @param callback The callback to add.
   */
  addCallback(callback) {
    if (!this.customCallbacks) {
      this.customCallbacks = [];
    }
    this.customCallbacks.push(callback);
    logger.debug(
      `ObservabilityManager: Added custom callback: ${callback.constructor.name}`
    );
  }
  /**
   * Clear all custom callbacks.
   */
  clearCallbacks() {
    this.customCallbacks = [];
    logger.debug("ObservabilityManager: Cleared all custom callbacks");
  }
  /**
   * Flush all pending traces to observability platforms.
   * Important for serverless environments and short-lived processes.
   */
  async flush() {
    const callbacks = await this.getCallbacks();
    for (const callback of callbacks) {
      if ("flushAsync" in callback && typeof callback.flushAsync === "function") {
        await callback.flushAsync();
      }
    }
    logger.debug("ObservabilityManager: All traces flushed");
  }
  /**
   * Shutdown all handlers gracefully (for serverless environments).
   */
  async shutdown() {
    await this.flush();
    const callbacks = await this.getCallbacks();
    for (const callback of callbacks) {
      if ("shutdownAsync" in callback && typeof callback.shutdownAsync === "function") {
        await callback.shutdownAsync();
      } else if ("shutdown" in callback && typeof callback.shutdown === "function") {
        await callback.shutdown();
      }
    }
    logger.debug("ObservabilityManager: All handlers shutdown");
  }
  /**
   * String representation of the ObservabilityManager.
   */
  toString() {
    const names = this.handlerNames;
    if (names.length > 0) {
      return `ObservabilityManager(handlers=${names.join(", ")})`;
    }
    return "ObservabilityManager(no handlers)";
  }
};

// src/agents/mcp_agent.ts
init_telemetry();
init_version();

// src/agents/prompts/system_prompt_builder.ts
var import_langchain = require("langchain");
function generateToolDescriptions(tools, disallowedTools) {
  const disallowedSet = new Set(disallowedTools ?? []);
  const descriptions = [];
  for (const tool of tools) {
    if (disallowedSet.has(tool.name)) continue;
    const escaped = tool.description.replace(/\{/g, "{{").replace(/\}/g, "}}");
    descriptions.push(`- ${tool.name}: ${escaped}`);
  }
  return descriptions;
}
__name(generateToolDescriptions, "generateToolDescriptions");
function buildSystemPromptContent(template, toolDescriptionLines, additionalInstructions) {
  const block = toolDescriptionLines.join("\n");
  let content;
  if (template.includes("{tool_descriptions}")) {
    content = template.replace("{tool_descriptions}", block);
  } else {
    console.warn(
      "`{tool_descriptions}` placeholder not found; appending at end."
    );
    content = `${template}

Available tools:
${block}`;
  }
  if (additionalInstructions) {
    content += `

${additionalInstructions}`;
  }
  return content;
}
__name(buildSystemPromptContent, "buildSystemPromptContent");
function createSystemMessage(tools, systemPromptTemplate, serverManagerTemplate, useServerManager, disallowedTools, userProvidedPrompt, additionalInstructions) {
  if (userProvidedPrompt) {
    return new import_langchain.SystemMessage({ content: userProvidedPrompt });
  }
  const template = useServerManager ? serverManagerTemplate : systemPromptTemplate;
  const toolLines = generateToolDescriptions(tools, disallowedTools);
  const finalContent = buildSystemPromptContent(
    template,
    toolLines,
    additionalInstructions
  );
  return new import_langchain.SystemMessage({ content: finalContent });
}
__name(createSystemMessage, "createSystemMessage");

// src/agents/prompts/templates.ts
var DEFAULT_SYSTEM_PROMPT_TEMPLATE = `You are a helpful AI assistant.
You have access to the following tools:

{tool_descriptions}

Use the following format:

Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of the available tools
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can repeat N times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question`;
var SERVER_MANAGER_SYSTEM_PROMPT_TEMPLATE = `You are a helpful assistant designed to interact with MCP
 (Model Context Protocol) servers. You can manage connections to different servers and use the tools
 provided by the currently active server.

Important: The available tools change depending on which server is active.
If a request requires tools not listed below (e.g., file operations, web browsing,
 image manipulation), you MUST first connect to the appropriate server using
 'connect_to_mcp_server'.
Use 'list_mcp_servers' to find the relevant server if you are unsure.
Only after successfully connecting and seeing the new tools listed in
the response should you attempt to use those server-specific tools.
Before attempting a task that requires specific tools, you should
ensure you are connected to the correct server and aware of its
available tools. If unsure, use 'list_mcp_servers' to see options
or 'get_active_mcp_server' to check the current connection.

When you connect to a server using 'connect_to_mcp_server',
 you will be informed about the new tools that become available.
You can then use these server-specific tools in subsequent steps.

Here are the tools *currently* available to you (this list includes server management tools and will
 change when you connect to a server):
{tool_descriptions}
`;

// src/agents/remote.ts
var import_zod8 = require("zod");
init_logging();
var API_CHATS_ENDPOINT = "/api/v1/chats";
var API_CHAT_EXECUTE_ENDPOINT = "/api/v1/chats/{chat_id}/execute";
function normalizeRemoteRunOptions(queryOrOptions, maxSteps, manageConnector, externalHistory, outputSchema) {
  if (typeof queryOrOptions === "object" && queryOrOptions !== null) {
    const options = queryOrOptions;
    return {
      query: options.prompt,
      maxSteps: options.maxSteps,
      manageConnector: options.manageConnector,
      externalHistory: options.externalHistory,
      outputSchema: options.schema
    };
  }
  return {
    query: queryOrOptions,
    maxSteps,
    manageConnector,
    externalHistory,
    outputSchema
  };
}
__name(normalizeRemoteRunOptions, "normalizeRemoteRunOptions");
var RemoteAgent = class {
  static {
    __name(this, "RemoteAgent");
  }
  agentId;
  apiKey;
  baseUrl;
  chatId = null;
  constructor(options) {
    this.agentId = options.agentId;
    this.baseUrl = options.baseUrl ?? "https://cloud.mcp-use.com";
    const apiKey = options.apiKey ?? (typeof process !== "undefined" && process.env?.MCP_USE_API_KEY);
    if (!apiKey) {
      throw new Error(
        "API key is required for remote execution. Please provide it as a parameter or set the MCP_USE_API_KEY environment variable. You can get an API key from https://cloud.mcp-use.com"
      );
    }
    this.apiKey = apiKey;
  }
  pydanticToJsonSchema(schema) {
    return (0, import_zod8.toJSONSchema)(schema);
  }
  parseStructuredResponse(responseData, outputSchema) {
    let resultData;
    if (typeof responseData === "object" && responseData !== null) {
      if ("result" in responseData) {
        const outerResult = responseData.result;
        if (typeof outerResult === "object" && outerResult !== null && "result" in outerResult) {
          resultData = outerResult.result;
        } else {
          resultData = outerResult;
        }
      } else {
        resultData = responseData;
      }
    } else if (typeof responseData === "string") {
      try {
        resultData = JSON.parse(responseData);
      } catch {
        resultData = { content: responseData };
      }
    } else {
      resultData = responseData;
    }
    try {
      return outputSchema.parse(resultData);
    } catch (e) {
      logger.warn(`Failed to parse structured output: ${e}`);
      const schemaShape = outputSchema._def?.shape();
      if (schemaShape && "content" in schemaShape) {
        return outputSchema.parse({ content: String(resultData) });
      }
      throw e;
    }
  }
  async createChatSession() {
    const chatPayload = {
      title: `Remote Agent Session - ${this.agentId}`,
      agent_id: this.agentId,
      type: "agent_execution"
    };
    const headers = {
      "Content-Type": "application/json",
      "x-api-key": this.apiKey
    };
    const chatUrl = `${this.baseUrl}${API_CHATS_ENDPOINT}`;
    logger.info(`\u{1F4DD} Creating chat session for agent ${this.agentId}`);
    try {
      const response = await fetch(chatUrl, {
        method: "POST",
        headers,
        body: JSON.stringify(chatPayload)
      });
      if (!response.ok) {
        const responseText = await response.text();
        const statusCode = response.status;
        if (statusCode === 404) {
          throw new Error(
            `Agent not found: Agent '${this.agentId}' does not exist or you don't have access to it. Please verify the agent ID and ensure it exists in your account.`
          );
        }
        throw new Error(
          `Failed to create chat session: ${statusCode} - ${responseText}`
        );
      }
      const chatData = await response.json();
      const chatId = chatData.id;
      logger.info(`\u2705 Chat session created: ${chatId}`);
      return chatId;
    } catch (e) {
      if (e instanceof Error) {
        throw new TypeError(`Failed to create chat session: ${e.message}`);
      }
      throw new Error(`Failed to create chat session: ${String(e)}`);
    }
  }
  async run(queryOrOptions, maxSteps, manageConnector, externalHistory, outputSchema) {
    const {
      query,
      maxSteps: steps,
      externalHistory: history,
      outputSchema: schema
    } = normalizeRemoteRunOptions(
      queryOrOptions,
      maxSteps,
      manageConnector,
      externalHistory,
      outputSchema
    );
    if (history !== void 0) {
      logger.warn("External history is not yet supported for remote execution");
    }
    try {
      logger.info(`\u{1F310} Executing query on remote agent ${this.agentId}`);
      if (this.chatId === null) {
        this.chatId = await this.createChatSession();
      }
      const chatId = this.chatId;
      const executionPayload = {
        query,
        max_steps: steps ?? 10
      };
      if (schema) {
        executionPayload.output_schema = this.pydanticToJsonSchema(schema);
        logger.info(`\u{1F527} Using structured output with schema`);
      }
      const headers = {
        "Content-Type": "application/json",
        "x-api-key": this.apiKey
      };
      const executionUrl = `${this.baseUrl}${API_CHAT_EXECUTE_ENDPOINT.replace("{chat_id}", chatId)}`;
      logger.info(`\u{1F680} Executing agent in chat ${chatId}`);
      const response = await fetch(executionUrl, {
        method: "POST",
        headers,
        body: JSON.stringify(executionPayload),
        signal: AbortSignal.timeout(3e5)
        // 5 minute timeout
      });
      if (!response.ok) {
        const responseText = await response.text();
        const statusCode = response.status;
        if (statusCode === 401) {
          logger.error(`\u274C Authentication failed: ${responseText}`);
          throw new Error(
            "Authentication failed: Invalid or missing API key. Please check your API key and ensure the MCP_USE_API_KEY environment variable is set correctly."
          );
        } else if (statusCode === 403) {
          logger.error(`\u274C Access forbidden: ${responseText}`);
          throw new Error(
            `Access denied: You don't have permission to execute agent '${this.agentId}'. Check if the agent exists and you have the necessary permissions.`
          );
        } else if (statusCode === 404) {
          logger.error(`\u274C Agent not found: ${responseText}`);
          throw new Error(
            `Agent not found: Agent '${this.agentId}' does not exist or you don't have access to it. Please verify the agent ID and ensure it exists in your account.`
          );
        } else if (statusCode === 422) {
          logger.error(`\u274C Validation error: ${responseText}`);
          throw new Error(
            `Request validation failed: ${responseText}. Please check your query parameters and output schema format.`
          );
        } else if (statusCode === 500) {
          logger.error(`\u274C Server error: ${responseText}`);
          throw new Error(
            "Internal server error occurred during agent execution. Please try again later or contact support if the issue persists."
          );
        } else {
          logger.error(
            `\u274C Remote execution failed with status ${statusCode}: ${responseText}`
          );
          throw new Error(
            `Remote agent execution failed: ${statusCode} - ${responseText}`
          );
        }
      }
      const result = await response.json();
      logger.info(`\u{1F527} Response: ${JSON.stringify(result)}`);
      logger.info("\u2705 Remote execution completed successfully");
      if (typeof result === "object" && result !== null) {
        if (result.status === "error" || result.error !== null) {
          const errorMsg = result.error ?? String(result);
          logger.error(`\u274C Remote agent execution failed: ${errorMsg}`);
          throw new Error(`Remote agent execution failed: ${errorMsg}`);
        }
        if (String(result).includes("failed to initialize")) {
          logger.error(`\u274C Agent initialization failed: ${result}`);
          throw new Error(
            `Agent initialization failed on remote server. This usually indicates:
\u2022 Invalid agent configuration (LLM model, system prompt)
\u2022 Missing or invalid MCP server configurations
\u2022 Network connectivity issues with MCP servers
\u2022 Missing environment variables or credentials
Raw error: ${result}`
          );
        }
      }
      if (schema) {
        return this.parseStructuredResponse(result, schema);
      }
      if (typeof result === "object" && result !== null && "result" in result) {
        return result.result;
      } else if (typeof result === "string") {
        return result;
      } else {
        return String(result);
      }
    } catch (e) {
      if (e instanceof Error) {
        if (e.name === "AbortError") {
          logger.error(`\u274C Remote execution timed out: ${e}`);
          throw new Error(
            "Remote agent execution timed out. The server may be overloaded or the query is taking too long to process. Try again or use a simpler query."
          );
        }
        logger.error(`\u274C Remote execution error: ${e}`);
        throw new Error(`Remote agent execution failed: ${e.message}`);
      }
      logger.error(`\u274C Remote execution error: ${e}`);
      throw new Error(`Remote agent execution failed: ${String(e)}`);
    }
  }
  // eslint-disable-next-line require-yield
  async *stream(queryOrOptions, maxSteps, manageConnector, externalHistory, outputSchema) {
    const result = await this.run(
      queryOrOptions,
      maxSteps,
      manageConnector,
      externalHistory,
      outputSchema
    );
    return result;
  }
  async close() {
    logger.info("\u{1F50C} Remote agent client closed");
  }
};

// src/agents/utils/llm_provider.ts
init_logging();
var PROVIDER_CONFIG = {
  openai: {
    package: "@langchain/openai",
    className: "ChatOpenAI",
    envVars: ["OPENAI_API_KEY"],
    defaultModel: "gpt-4o"
  },
  anthropic: {
    package: "@langchain/anthropic",
    className: "ChatAnthropic",
    envVars: ["ANTHROPIC_API_KEY"],
    defaultModel: "claude-3-5-sonnet-20241022"
  },
  google: {
    package: "@langchain/google-genai",
    className: "ChatGoogleGenerativeAI",
    envVars: ["GOOGLE_API_KEY", "GOOGLE_GENERATIVE_AI_API_KEY"],
    defaultModel: "gemini-pro"
  },
  groq: {
    package: "@langchain/groq",
    className: "ChatGroq",
    envVars: ["GROQ_API_KEY"],
    defaultModel: "llama-3.1-70b-versatile"
  }
};
function parseLLMString(llmString) {
  const parts = llmString.split("/");
  if (parts.length !== 2) {
    throw new Error(
      `Invalid LLM string format. Expected 'provider/model', got '${llmString}'. Examples: 'openai/gpt-4', 'anthropic/claude-3-5-sonnet-20241022', 'google/gemini-pro', 'groq/llama-3.1-70b-versatile'`
    );
  }
  const [provider, model] = parts;
  if (!provider || !model) {
    throw new Error(
      `Invalid LLM string format. Both provider and model must be non-empty. Got '${llmString}'`
    );
  }
  const normalizedProvider = provider.toLowerCase();
  if (!(normalizedProvider in PROVIDER_CONFIG)) {
    const supportedProviders = Object.keys(PROVIDER_CONFIG).join(", ");
    throw new Error(
      `Unsupported LLM provider '${provider}'. Supported providers: ${supportedProviders}`
    );
  }
  return { provider: normalizedProvider, model };
}
__name(parseLLMString, "parseLLMString");
function getAPIKey(provider, config) {
  if (config?.apiKey) {
    return config.apiKey;
  }
  const providerConfig = PROVIDER_CONFIG[provider];
  if (typeof process !== "undefined" && process.env) {
    for (const envVar of providerConfig.envVars) {
      const apiKey = process.env[envVar];
      if (apiKey) {
        logger.debug(
          `Using API key from environment variable ${envVar} for provider ${provider}`
        );
        return apiKey;
      }
    }
  }
  const envVarsStr = providerConfig.envVars.join(" or ");
  throw new Error(
    `API key not found for provider '${provider}'. Set ${envVarsStr} environment variable or pass apiKey in llmConfig. Example: new MCPAgent({ llm: '${provider}/model', llmConfig: { apiKey: 'your-key' } })`
  );
}
__name(getAPIKey, "getAPIKey");
async function createLLMFromString(llmString, config) {
  logger.info(`Creating LLM from string: ${llmString}`);
  const { provider, model } = parseLLMString(llmString);
  const providerConfig = PROVIDER_CONFIG[provider];
  const apiKey = getAPIKey(provider, config);
  let providerModule;
  try {
    logger.debug(`Importing package ${providerConfig.package}...`);
    providerModule = await import(providerConfig.package);
  } catch (error) {
    if (error?.code === "MODULE_NOT_FOUND" || error?.message?.includes("Cannot find module") || error?.message?.includes("Cannot find package")) {
      throw new Error(
        `Package '${providerConfig.package}' is not installed. Install it with: npm install ${providerConfig.package} or yarn add ${providerConfig.package}`
      );
    }
    throw new Error(
      `Failed to import ${providerConfig.package}: ${error?.message || error}`
    );
  }
  const LLMClass = providerModule[providerConfig.className];
  if (!LLMClass) {
    throw new Error(
      `Could not find ${providerConfig.className} in package ${providerConfig.package}. This might be a version compatibility issue.`
    );
  }
  const llmConfig = {
    model,
    apiKey,
    ...config
  };
  if (config?.apiKey) {
    delete llmConfig.apiKey;
    llmConfig.apiKey = apiKey;
  }
  if (provider === "anthropic") {
    llmConfig.model = model;
  } else if (provider === "google") {
    llmConfig.model = model;
  } else if (provider === "openai") {
    llmConfig.model = model;
  } else if (provider === "groq") {
    llmConfig.model = model;
  }
  try {
    const llmInstance = new LLMClass(llmConfig);
    logger.info(`Successfully created ${provider} LLM with model ${model}`);
    return llmInstance;
  } catch (error) {
    throw new Error(
      `Failed to instantiate ${providerConfig.className} with model '${model}': ${error?.message || error}`
    );
  }
}
__name(createLLMFromString, "createLLMFromString");
function isValidLLMString(llmString) {
  try {
    parseLLMString(llmString);
    return true;
  } catch {
    return false;
  }
}
__name(isValidLLMString, "isValidLLMString");
function getSupportedProviders() {
  return Object.keys(PROVIDER_CONFIG);
}
__name(getSupportedProviders, "getSupportedProviders");

// src/agents/mcp_agent.ts
function normalizeRunOptions(queryOrOptions, maxSteps, manageConnector, externalHistory, outputSchema) {
  if (typeof queryOrOptions === "object" && queryOrOptions !== null) {
    const options = queryOrOptions;
    return {
      query: options.prompt,
      maxSteps: options.maxSteps,
      manageConnector: options.manageConnector,
      externalHistory: options.externalHistory,
      outputSchema: options.schema
    };
  }
  return {
    query: queryOrOptions,
    maxSteps,
    manageConnector,
    externalHistory,
    outputSchema
  };
}
__name(normalizeRunOptions, "normalizeRunOptions");
var MCPAgent = class {
  static {
    __name(this, "MCPAgent");
  }
  /**
   * Get the mcp-use package version.
   * Works in all environments (Node.js, browser, Cloudflare Workers, Deno, etc.)
   */
  static getPackageVersion() {
    return getPackageVersion();
  }
  llm;
  client;
  connectors;
  maxSteps;
  autoInitialize;
  memoryEnabled;
  disallowedTools;
  additionalTools;
  toolsUsedNames = [];
  useServerManager;
  verbose;
  observe;
  systemPrompt;
  systemPromptTemplateOverride;
  additionalInstructions;
  _initialized = false;
  conversationHistory = [];
  _agentExecutor = null;
  sessions = {};
  systemMessage = null;
  _tools = [];
  adapter;
  serverManager = null;
  telemetry;
  modelProvider;
  modelName;
  // Observability support
  observabilityManager;
  callbacks = [];
  metadata = {};
  tags = [];
  // Remote agent support
  isRemote = false;
  remoteAgent = null;
  // Simplified mode support
  isSimplifiedMode = false;
  llmString;
  llmConfig;
  mcpServersConfig;
  clientOwnedByAgent = false;
  constructor(options) {
    if (options.agentId) {
      this.isRemote = true;
      this.remoteAgent = new RemoteAgent({
        agentId: options.agentId,
        apiKey: options.apiKey,
        baseUrl: options.baseUrl
      });
      this.maxSteps = options.maxSteps ?? 5;
      this.memoryEnabled = options.memoryEnabled ?? true;
      this.autoInitialize = options.autoInitialize ?? false;
      this.verbose = options.verbose ?? false;
      this.observe = options.observe ?? true;
      this.connectors = [];
      this.disallowedTools = [];
      this.additionalTools = [];
      this.useServerManager = false;
      this.adapter = new LangChainAdapter();
      this.telemetry = Telemetry.getInstance();
      this.modelProvider = "remote";
      this.modelName = "remote-agent";
      this.observabilityManager = new ObservabilityManager({
        customCallbacks: options.callbacks,
        agentId: options.agentId
      });
      this.callbacks = [];
      return;
    }
    if (!options.llm) {
      throw new Error(
        "llm is required for local execution. For remote execution, provide agentId instead."
      );
    }
    const isSimplifiedMode = typeof options.llm === "string";
    if (isSimplifiedMode) {
      this.isSimplifiedMode = true;
      this.llmString = options.llm;
      this.llmConfig = options.llmConfig;
      this.mcpServersConfig = options.mcpServers;
      if (!this.mcpServersConfig || Object.keys(this.mcpServersConfig).length === 0) {
        throw new Error(
          "Simplified mode requires 'mcpServers' configuration. Provide an object with server configurations, e.g., { filesystem: { command: 'npx', args: [...] } }"
        );
      }
      this.llm = void 0;
      this.client = void 0;
      this.clientOwnedByAgent = true;
      this.connectors = [];
      logger.info(
        `\u{1F3AF} Simplified mode enabled: LLM will be created from '${this.llmString}'`
      );
    } else {
      this.isSimplifiedMode = false;
      this.llm = options.llm;
      this.client = options.client;
      this.connectors = options.connectors ?? [];
      this.clientOwnedByAgent = false;
      if (!this.client && this.connectors.length === 0) {
        throw new Error(
          "Explicit mode requires either 'client' or at least one 'connector'. Alternatively, use simplified mode with 'llm' as a string and 'mcpServers' config."
        );
      }
    }
    this.maxSteps = options.maxSteps ?? 5;
    this.autoInitialize = options.autoInitialize ?? false;
    this.memoryEnabled = options.memoryEnabled ?? true;
    this.systemPrompt = options.systemPrompt ?? null;
    this.systemPromptTemplateOverride = options.systemPromptTemplate ?? null;
    this.additionalInstructions = options.additionalInstructions ?? null;
    this.disallowedTools = options.disallowedTools ?? [];
    this.additionalTools = options.additionalTools ?? [];
    this.toolsUsedNames = options.toolsUsedNames ?? [];
    this.useServerManager = options.useServerManager ?? false;
    this.verbose = options.verbose ?? false;
    this.observe = options.observe ?? true;
    if (!this.isSimplifiedMode) {
      if (this.useServerManager) {
        if (!this.client) {
          throw new Error(
            "'client' must be provided when 'useServerManager' is true."
          );
        }
        this.adapter = options.adapter ?? new LangChainAdapter(this.disallowedTools);
        this.serverManager = options.serverManagerFactory?.(this.client) ?? new ServerManager(this.client, this.adapter);
      } else {
        this.adapter = options.adapter ?? new LangChainAdapter(this.disallowedTools);
      }
      this.telemetry = Telemetry.getInstance();
      if (this.llm) {
        const [provider, name] = extractModelInfo(this.llm);
        this.modelProvider = provider;
        this.modelName = name;
      } else {
        this.modelProvider = "unknown";
        this.modelName = "unknown";
      }
    } else {
      this.adapter = options.adapter ?? new LangChainAdapter(this.disallowedTools);
      this.telemetry = Telemetry.getInstance();
      this.modelProvider = "unknown";
      this.modelName = "unknown";
    }
    this.observabilityManager = new ObservabilityManager({
      customCallbacks: options.callbacks,
      verbose: this.verbose,
      observe: this.observe,
      agentId: options.agentId,
      metadataProvider: /* @__PURE__ */ __name(() => this.getMetadata(), "metadataProvider"),
      tagsProvider: /* @__PURE__ */ __name(() => this.getTags(), "tagsProvider")
    });
    Object.defineProperty(this, "agentExecutor", {
      get: /* @__PURE__ */ __name(() => this._agentExecutor, "get"),
      configurable: true
    });
    Object.defineProperty(this, "tools", {
      get: /* @__PURE__ */ __name(() => this._tools, "get"),
      configurable: true
    });
    Object.defineProperty(this, "initialized", {
      get: /* @__PURE__ */ __name(() => this._initialized, "get"),
      configurable: true
    });
  }
  async initialize() {
    if (this.isRemote) {
      this._initialized = true;
      return;
    }
    logger.info("\u{1F680} Initializing MCP agent and connecting to services...");
    if (this.isSimplifiedMode) {
      logger.info(
        "\u{1F3AF} Simplified mode: Creating client and LLM from configuration..."
      );
      if (this.mcpServersConfig) {
        logger.info(
          `Creating MCPClient with ${Object.keys(this.mcpServersConfig).length} server(s)...`
        );
        const { MCPClient: MCPClient2 } = await Promise.resolve().then(() => (init_client(), client_exports));
        this.client = new MCPClient2({ mcpServers: this.mcpServersConfig });
        logger.info("\u2705 MCPClient created successfully");
      }
      if (this.llmString) {
        logger.info(`Creating LLM from string: ${this.llmString}...`);
        try {
          this.llm = await createLLMFromString(this.llmString, this.llmConfig);
          logger.info("\u2705 LLM created successfully");
          const [provider, name] = extractModelInfo(this.llm);
          this.modelProvider = provider;
          this.modelName = name;
        } catch (error) {
          throw new Error(
            `Failed to create LLM from string '${this.llmString}': ${error?.message || error}`
          );
        }
      }
      if (this.useServerManager) {
        if (!this.client) {
          throw new Error(
            "'client' must be available when 'useServerManager' is true."
          );
        }
        this.serverManager = new ServerManager(this.client, this.adapter);
      }
    }
    this.callbacks = await this.observabilityManager.getCallbacks();
    const handlerNames = await this.observabilityManager.getHandlerNames();
    if (handlerNames.length > 0) {
      logger.info(`\u{1F4CA} Observability enabled with: ${handlerNames.join(", ")}`);
    }
    if (this.useServerManager && this.serverManager) {
      await this.serverManager.initialize();
      const managementTools = this.serverManager.tools;
      this._tools = managementTools;
      this._tools.push(...this.additionalTools);
      logger.info(
        `\u{1F527} Server manager mode active with ${managementTools.length} management tools`
      );
      await this.createSystemMessageFromTools(this._tools);
    } else {
      if (this.client) {
        this.sessions = this.client.getAllActiveSessions();
        logger.info(
          `\u{1F50C} Found ${Object.keys(this.sessions).length} existing sessions`
        );
        const nonCodeModeSessions = Object.keys(this.sessions).filter(
          (name) => name !== "code_mode"
        );
        if (nonCodeModeSessions.length === 0) {
          logger.info("\u{1F504} No active sessions found, creating new ones...");
          this.sessions = await this.client.createAllSessions();
          logger.info(
            `\u2705 Created ${Object.keys(this.sessions).length} new sessions`
          );
        }
        if (this.client.codeMode) {
          const codeModeSession = this.sessions["code_mode"];
          if (codeModeSession) {
            this._tools = await this.adapter.createToolsFromConnectors([
              codeModeSession.connector
            ]);
            logger.info(`\u{1F6E0}\uFE0F Created ${this._tools.length} code mode tools`);
          } else {
            throw new Error(
              "Code mode enabled but code_mode session not found"
            );
          }
        } else {
          const tools = await this.adapter.createToolsFromConnectors(
            Object.values(this.sessions).map((session) => session.connector)
          );
          const resources = await this.adapter.createResourcesFromConnectors(
            Object.values(this.sessions).map((session) => session.connector)
          );
          const prompts = await this.adapter.createPromptsFromConnectors(
            Object.values(this.sessions).map((session) => session.connector)
          );
          this._tools = [...tools, ...resources, ...prompts];
          logger.info(
            `\u{1F6E0}\uFE0F Created ${this._tools.length} LangChain items from client: ${tools.length} tools, ${resources.length} resources, ${prompts.length} prompts`
          );
        }
        this._tools.push(...this.additionalTools);
      } else {
        logger.info(
          `\u{1F517} Connecting to ${this.connectors.length} direct connectors...`
        );
        for (const connector of this.connectors) {
          if (!connector.isClientConnected) {
            await connector.connect();
          }
        }
        const tools = await this.adapter.createToolsFromConnectors(
          this.connectors
        );
        const resources = await this.adapter.createResourcesFromConnectors(
          this.connectors
        );
        const prompts = await this.adapter.createPromptsFromConnectors(
          this.connectors
        );
        this._tools = [...tools, ...resources, ...prompts];
        this._tools.push(...this.additionalTools);
        logger.info(
          `\u{1F6E0}\uFE0F Created ${this._tools.length} LangChain items from connectors: ${tools.length} tools, ${resources.length} resources, ${prompts.length} prompts`
        );
      }
      logger.info(`\u{1F9F0} Found ${this._tools.length} tools across all connectors`);
      await this.createSystemMessageFromTools(this._tools);
    }
    this._agentExecutor = this.createAgent();
    this._initialized = true;
    const mcpServerInfo = this.getMCPServerInfo();
    if (Object.keys(mcpServerInfo).length > 0) {
      this.setMetadata(mcpServerInfo);
      logger.debug(
        `MCP server info added to metadata: ${JSON.stringify(mcpServerInfo)}`
      );
    }
    logger.info("\u2728 Agent initialization complete");
  }
  async createSystemMessageFromTools(tools) {
    const systemPromptTemplate = this.systemPromptTemplateOverride ?? DEFAULT_SYSTEM_PROMPT_TEMPLATE;
    this.systemMessage = createSystemMessage(
      tools,
      systemPromptTemplate,
      SERVER_MANAGER_SYSTEM_PROMPT_TEMPLATE,
      this.useServerManager,
      this.disallowedTools,
      this.systemPrompt ?? void 0,
      this.additionalInstructions ?? void 0
    );
    if (this.memoryEnabled) {
      this.conversationHistory = [
        this.systemMessage,
        ...this.conversationHistory.filter(
          (m) => !(m instanceof import_langchain2.SystemMessage)
        )
      ];
    }
  }
  createAgent() {
    if (!this.llm) {
      throw new Error("LLM is required to create agent");
    }
    const systemContent = this.systemMessage?.content ?? "You are a helpful assistant.";
    const toolNames = this._tools.map((tool) => tool.name);
    logger.info(`\u{1F9E0} Agent ready with tools: ${toolNames.join(", ")}`);
    const middleware = [(0, import_langchain2.modelCallLimitMiddleware)({ runLimit: this.maxSteps })];
    const agent = (0, import_langchain2.createAgent)({
      model: this.llm,
      tools: this._tools,
      systemPrompt: systemContent,
      middleware
    });
    logger.debug(
      `Created agent with max_steps=${this.maxSteps} (via ModelCallLimitMiddleware) and ${this.callbacks.length} callbacks`
    );
    return agent;
  }
  getConversationHistory() {
    return [...this.conversationHistory];
  }
  clearConversationHistory() {
    this.conversationHistory = this.memoryEnabled && this.systemMessage ? [this.systemMessage] : [];
  }
  addToHistory(message) {
    if (this.memoryEnabled) this.conversationHistory.push(message);
  }
  getSystemMessage() {
    return this.systemMessage;
  }
  setSystemMessage(message) {
    this.systemMessage = new import_langchain2.SystemMessage(message);
    if (this.memoryEnabled) {
      this.conversationHistory = this.conversationHistory.filter(
        (m) => !(m instanceof import_langchain2.SystemMessage)
      );
      this.conversationHistory.unshift(this.systemMessage);
    }
    if (this._initialized && this._tools.length) {
      this._agentExecutor = this.createAgent();
      logger.debug("Agent recreated with new system message");
    }
  }
  setDisallowedTools(disallowedTools) {
    this.disallowedTools = disallowedTools;
    this.adapter = new LangChainAdapter(this.disallowedTools);
    if (this._initialized) {
      logger.debug(
        "Agent already initialized. Changes will take effect on next initialization."
      );
    }
  }
  getDisallowedTools() {
    return this.disallowedTools;
  }
  /**
   * Set metadata for observability traces
   * @param newMetadata - Key-value pairs to add to metadata. Keys should be strings, values should be serializable.
   */
  setMetadata(newMetadata) {
    const sanitizedMetadata = this.sanitizeMetadata(newMetadata);
    this.metadata = { ...this.metadata, ...sanitizedMetadata };
    logger.debug(`Metadata set: ${JSON.stringify(this.metadata)}`);
  }
  /**
   * Get current metadata
   * @returns A copy of the current metadata object
   */
  getMetadata() {
    return { ...this.metadata };
  }
  /**
   * Set tags for observability traces
   * @param newTags - Array of tag strings to add. Duplicates will be automatically removed.
   */
  setTags(newTags) {
    const sanitizedTags = this.sanitizeTags(newTags);
    this.tags = [.../* @__PURE__ */ new Set([...this.tags, ...sanitizedTags])];
    logger.debug(`Tags set: ${JSON.stringify(this.tags)}`);
  }
  /**
   * Get current tags
   * @returns A copy of the current tags array
   */
  getTags() {
    return [...this.tags];
  }
  /**
   * Sanitize metadata to ensure compatibility with observability platforms
   * @param metadata - Raw metadata object
   * @returns Sanitized metadata object
   */
  sanitizeMetadata(metadata) {
    const sanitized = {};
    for (const [key, value] of Object.entries(metadata)) {
      if (typeof key !== "string" || key.length === 0) {
        logger.warn(`Invalid metadata key: ${key}. Skipping.`);
        continue;
      }
      const sanitizedKey = key.replace(/[^\w-]/g, "_");
      if (value === null || value === void 0) {
        sanitized[sanitizedKey] = value;
      } else if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
        sanitized[sanitizedKey] = value;
      } else if (Array.isArray(value)) {
        const sanitizedArray = value.filter(
          (item) => typeof item === "string" || typeof item === "number" || typeof item === "boolean"
        );
        if (sanitizedArray.length > 0) {
          sanitized[sanitizedKey] = sanitizedArray;
        }
      } else if (typeof value === "object") {
        try {
          const serialized = JSON.stringify(value);
          if (serialized.length > 1e3) {
            logger.warn(
              `Metadata value for key '${sanitizedKey}' is too large. Truncating.`
            );
            sanitized[sanitizedKey] = `${serialized.substring(0, 1e3)}...`;
          } else {
            sanitized[sanitizedKey] = value;
          }
        } catch (error) {
          logger.warn(
            `Failed to serialize metadata value for key '${sanitizedKey}': ${error}. Skipping.`
          );
        }
      } else {
        logger.warn(
          `Unsupported metadata value type for key '${sanitizedKey}': ${typeof value}. Skipping.`
        );
      }
    }
    return sanitized;
  }
  /**
   * Sanitize tags to ensure compatibility with observability platforms
   * @param tags - Array of tag strings
   * @returns Array of sanitized tag strings
   */
  sanitizeTags(tags) {
    return tags.filter((tag) => typeof tag === "string" && tag.length > 0).map((tag) => tag.replace(/[^\w:-]/g, "_")).filter((tag) => tag.length <= 50);
  }
  /**
   * Get MCP server information for observability metadata
   */
  getMCPServerInfo() {
    const serverInfo = {};
    try {
      if (this.client) {
        const serverNames = this.client.getServerNames();
        serverInfo.mcp_servers_count = serverNames.length;
        serverInfo.mcp_server_names = serverNames;
        const serverConfigs = {};
        for (const serverName of serverNames) {
          try {
            const config = this.client.getServerConfig(serverName);
            if (config) {
              let serverType = "unknown";
              if (config.command) {
                serverType = "command";
              } else if (config.url) {
                serverType = "http";
              } else if (config.ws_url) {
                serverType = "websocket";
              }
              serverConfigs[serverName] = {
                type: serverType,
                // Include safe configuration details (avoid sensitive data)
                has_args: !!config.args,
                has_env: !!config.env,
                has_headers: !!config.headers,
                url: config.url || null,
                command: config.command || null
              };
            }
          } catch (error) {
            logger.warn(
              `Failed to get config for server '${serverName}': ${error}`
            );
            serverConfigs[serverName] = {
              type: "error",
              error: "config_unavailable"
            };
          }
        }
        serverInfo.mcp_server_configs = serverConfigs;
      } else if (this.connectors && this.connectors.length > 0) {
        serverInfo.mcp_servers_count = this.connectors.length;
        serverInfo.mcp_server_names = this.connectors.map(
          (c) => c.publicIdentifier
        );
        serverInfo.mcp_server_types = this.connectors.map(
          (c) => c.constructor.name
        );
      }
    } catch (error) {
      logger.warn(`Failed to collect MCP server info: ${error}`);
      serverInfo.error = "collection_failed";
    }
    return serverInfo;
  }
  _normalizeOutput(value) {
    try {
      if (typeof value === "string") {
        return value;
      }
      if (value && typeof value === "object" && "content" in value) {
        return this._normalizeOutput(value.content);
      }
      if (Array.isArray(value)) {
        const parts = [];
        for (const item of value) {
          if (typeof item === "object" && item !== null) {
            if ("text" in item && typeof item.text === "string") {
              parts.push(item.text);
            } else if ("content" in item) {
              parts.push(this._normalizeOutput(item.content));
            } else {
              parts.push(String(item));
            }
          } else {
            const partText = item && typeof item === "object" && "text" in item ? item.text : null;
            if (typeof partText === "string") {
              parts.push(partText);
            } else {
              const partContent = item && typeof item === "object" && "content" in item ? item.content : item;
              parts.push(this._normalizeOutput(partContent));
            }
          }
        }
        return parts.join("");
      }
      return String(value);
    } catch (error) {
      return String(value);
    }
  }
  /**
   * Check if a message is AI/assistant-like regardless of whether it's a class instance.
   * Handles version mismatches, serialization boundaries, and different message formats.
   *
   * This method solves the issue where messages from LangChain agents may be plain JavaScript
   * objects (e.g., `{ type: 'ai', content: '...' }`) instead of AIMessage instances due to
   * serialization/deserialization across module boundaries or version mismatches.
   *
   * @example
   * // Real AIMessage instance (standard case)
   * _isAIMessageLike(new AIMessage("hello")) // => true
   *
   * @example
   * // Plain object after serialization (fixes issue #446)
   * _isAIMessageLike({ type: "ai", content: "hello" }) // => true
   *
   * @example
   * // OpenAI-style format with role
   * _isAIMessageLike({ role: "assistant", content: "hello" }) // => true
   *
   * @example
   * // Object with getType() method
   * _isAIMessageLike({ getType: () => "ai", content: "hello" }) // => true
   *
   * @param message - The message object to check
   * @returns true if the message represents an AI/assistant message
   */
  _isAIMessageLike(message) {
    if (message instanceof import_langchain2.AIMessage) {
      return true;
    }
    if (typeof message !== "object" || message === null) {
      return false;
    }
    const msg = message;
    if (typeof msg.getType === "function") {
      try {
        const type = msg.getType();
        if (type === "ai" || type === "assistant") {
          return true;
        }
      } catch (error) {
      }
    }
    if (typeof msg._getType === "function") {
      try {
        const type = msg._getType();
        if (type === "ai" || type === "assistant") {
          return true;
        }
      } catch (error) {
      }
    }
    if ("type" in msg) {
      return msg.type === "ai" || msg.type === "assistant";
    }
    if ("role" in msg) {
      return msg.role === "ai" || msg.role === "assistant";
    }
    return false;
  }
  /**
   * Check if a message has tool calls, handling both class instances and plain objects.
   * Safely checks for tool_calls array presence.
   *
   * @example
   * // AIMessage with tool calls
   * const msg = new AIMessage({ content: "", tool_calls: [{ name: "add", args: {} }] });
   * _messageHasToolCalls(msg) // => true
   *
   * @example
   * // Plain object with tool calls
   * _messageHasToolCalls({ type: "ai", tool_calls: [{ name: "add" }] }) // => true
   *
   * @example
   * // Message without tool calls
   * _messageHasToolCalls({ type: "ai", content: "hello" }) // => false
   *
   * @param message - The message object to check
   * @returns true if the message has non-empty tool_calls array
   */
  _messageHasToolCalls(message) {
    if (typeof message === "object" && message !== null && "tool_calls" in message && Array.isArray(message.tool_calls)) {
      return message.tool_calls.length > 0;
    }
    return false;
  }
  /**
   * Check if a message is a HumanMessage-like object.
   * Handles both class instances and plain objects from serialization.
   *
   * @example
   * _isHumanMessageLike(new HumanMessage("hello")) // => true
   * _isHumanMessageLike({ type: "human", content: "hello" }) // => true
   *
   * @param message - The message object to check
   * @returns true if the message represents a human message
   */
  _isHumanMessageLike(message) {
    if (message instanceof import_langchain2.HumanMessage) {
      return true;
    }
    if (typeof message !== "object" || message === null) {
      return false;
    }
    const msg = message;
    if (typeof msg.getType === "function") {
      try {
        const type = msg.getType();
        if (type === "human" || type === "user") {
          return true;
        }
      } catch (error) {
      }
    }
    if ("type" in msg && (msg.type === "human" || msg.type === "user")) {
      return true;
    }
    if ("role" in msg && (msg.role === "human" || msg.role === "user")) {
      return true;
    }
    return false;
  }
  /**
   * Check if a message is a ToolMessage-like object.
   * Handles both class instances and plain objects from serialization.
   *
   * @example
   * _isToolMessageLike(new ToolMessage({ content: "result", tool_call_id: "123" })) // => true
   * _isToolMessageLike({ type: "tool", content: "result" }) // => true
   *
   * @param message - The message object to check
   * @returns true if the message represents a tool message
   */
  _isToolMessageLike(message) {
    if (message instanceof import_langchain2.ToolMessage) {
      return true;
    }
    if (typeof message !== "object" || message === null) {
      return false;
    }
    const msg = message;
    if (typeof msg.getType === "function") {
      try {
        const type = msg.getType();
        if (type === "tool") {
          return true;
        }
      } catch (error) {
      }
    }
    if ("type" in msg && msg.type === "tool") {
      return true;
    }
    return false;
  }
  /**
   * Extract content from a message, handling both AIMessage instances and plain objects.
   *
   * @example
   * // From AIMessage instance
   * _getMessageContent(new AIMessage("hello")) // => "hello"
   *
   * @example
   * // From plain object
   * _getMessageContent({ type: "ai", content: "hello" }) // => "hello"
   *
   * @param message - The message object to extract content from
   * @returns The content of the message, or undefined if not present
   */
  _getMessageContent(message) {
    if (message instanceof import_langchain2.AIMessage) {
      return message.content;
    }
    if (message && typeof message === "object" && "content" in message) {
      return message.content;
    }
    return void 0;
  }
  async _consumeAndReturn(generator) {
    while (true) {
      const { done, value } = await generator.next();
      if (done) {
        return value;
      }
    }
  }
  async run(queryOrOptions, maxSteps, manageConnector, externalHistory, outputSchema) {
    const {
      query,
      maxSteps: steps,
      manageConnector: manage,
      externalHistory: history,
      outputSchema: schema
    } = normalizeRunOptions(
      queryOrOptions,
      maxSteps,
      manageConnector,
      externalHistory,
      outputSchema
    );
    if (this.isRemote && this.remoteAgent) {
      return this.remoteAgent.run(query, steps, manage, history, schema);
    }
    const generator = this.stream(query, steps, manage, history, schema);
    return this._consumeAndReturn(generator);
  }
  async *stream(queryOrOptions, maxSteps, manageConnector = true, externalHistory, outputSchema) {
    const {
      query,
      maxSteps: steps,
      manageConnector: manage,
      externalHistory: history,
      outputSchema: schema
    } = normalizeRunOptions(
      queryOrOptions,
      maxSteps,
      manageConnector,
      externalHistory,
      outputSchema
    );
    if (this.isRemote && this.remoteAgent) {
      const result = await this.remoteAgent.run(
        query,
        steps,
        manage,
        history,
        schema
      );
      return result;
    }
    let initializedHere = false;
    const startTime = Date.now();
    let success = false;
    let finalOutput = null;
    let stepsTaken = 0;
    try {
      if (manage && !this._initialized) {
        await this.initialize();
        initializedHere = true;
      } else if (!this._initialized && this.autoInitialize) {
        await this.initialize();
        initializedHere = true;
      }
      if (!this._agentExecutor) {
        throw new Error("MCP agent failed to initialize");
      }
      if (this.useServerManager && this.serverManager) {
        const currentTools = this.serverManager.tools;
        const currentToolNames = new Set(currentTools.map((t) => t.name));
        const existingToolNames = new Set(this._tools.map((t) => t.name));
        if (currentToolNames.size !== existingToolNames.size || [...currentToolNames].some((n) => !existingToolNames.has(n))) {
          logger.info(
            `\u{1F504} Tools changed before execution, updating agent. New tools: ${[...currentToolNames].join(", ")}`
          );
          this._tools = currentTools;
          this._tools.push(...this.additionalTools);
          await this.createSystemMessageFromTools(this._tools);
          this._agentExecutor = this.createAgent();
        }
      }
      const historyToUse = history ?? this.conversationHistory;
      const langchainHistory = [];
      for (const msg of historyToUse) {
        if (this._isHumanMessageLike(msg) || this._isAIMessageLike(msg) || this._isToolMessageLike(msg)) {
          langchainHistory.push(msg);
        }
      }
      const displayQuery = query.length > 50 ? `${query.slice(0, 50).replace(/\n/g, " ")}...` : query.replace(/\n/g, " ");
      logger.info(`\u{1F4AC} Received query: '${displayQuery}'`);
      logger.info("\u{1F3C1} Starting agent execution");
      const maxRestarts = 3;
      let restartCount = 0;
      const accumulatedMessages = [
        ...langchainHistory,
        new import_langchain2.HumanMessage(query)
      ];
      while (restartCount <= maxRestarts) {
        const inputs = { messages: accumulatedMessages };
        let shouldRestart = false;
        const stream = await this._agentExecutor.stream(inputs, {
          streamMode: "updates",
          // Get updates as they happen
          callbacks: this.callbacks,
          metadata: this.getMetadata(),
          tags: this.getTags(),
          // Set trace name for LangChain/Langfuse
          runName: this.metadata.trace_name || "mcp-use-agent",
          // Set recursion limit to 3x maxSteps to account for model calls + tool executions
          recursionLimit: this.maxSteps * 3,
          // Pass sessionId for Langfuse if present in metadata
          ...this.metadata.session_id && {
            sessionId: this.metadata.session_id
          }
        });
        for await (const chunk of stream) {
          for (const [nodeName, nodeOutput] of Object.entries(chunk)) {
            logger.debug(
              `\u{1F4E6} Node '${nodeName}' output: ${JSON.stringify(nodeOutput)}`
            );
            if (nodeOutput && typeof nodeOutput === "object" && "messages" in nodeOutput) {
              let messages = nodeOutput.messages;
              if (!Array.isArray(messages)) {
                messages = [messages];
              }
              for (const msg of messages) {
                if (!accumulatedMessages.includes(msg)) {
                  accumulatedMessages.push(msg);
                }
              }
              for (const message of messages) {
                if ("tool_calls" in message && Array.isArray(message.tool_calls) && message.tool_calls.length > 0) {
                  for (const toolCall of message.tool_calls) {
                    const toolName = toolCall.name || "unknown";
                    const toolInput = toolCall.args || {};
                    this.toolsUsedNames.push(toolName);
                    stepsTaken++;
                    let toolInputStr = JSON.stringify(toolInput);
                    if (toolInputStr.length > 100) {
                      toolInputStr = `${toolInputStr.slice(0, 97)}...`;
                    }
                    logger.info(
                      `\u{1F527} Tool call: ${toolName} with input: ${toolInputStr}`
                    );
                    yield {
                      action: {
                        tool: toolName,
                        toolInput,
                        log: `Calling tool ${toolName}`
                      },
                      observation: ""
                      // Will be filled in by tool result
                    };
                  }
                }
                if (this._isToolMessageLike(message)) {
                  const observation = message.content;
                  let observationStr = String(observation);
                  if (observationStr.length > 100) {
                    observationStr = `${observationStr.slice(0, 97)}...`;
                  }
                  observationStr = observationStr.replace(/\n/g, " ");
                  logger.info(`\u{1F4C4} Tool result: ${observationStr}`);
                  if (this.useServerManager && this.serverManager) {
                    const currentTools = this.serverManager.tools;
                    const currentToolNames = new Set(
                      currentTools.map((t) => t.name)
                    );
                    const existingToolNames = new Set(
                      this._tools.map((t) => t.name)
                    );
                    if (currentToolNames.size !== existingToolNames.size || [...currentToolNames].some(
                      (n) => !existingToolNames.has(n)
                    )) {
                      logger.info(
                        `\u{1F504} Tools changed during execution. New tools: ${[...currentToolNames].join(", ")}`
                      );
                      this._tools = currentTools;
                      this._tools.push(...this.additionalTools);
                      await this.createSystemMessageFromTools(this._tools);
                      this._agentExecutor = this.createAgent();
                      shouldRestart = true;
                      restartCount++;
                      logger.info(
                        `\u{1F503} Restarting execution with updated tools (restart ${restartCount}/${maxRestarts})`
                      );
                      break;
                    }
                  }
                }
                if (this._isAIMessageLike(message) && !this._messageHasToolCalls(message)) {
                  finalOutput = this._normalizeOutput(
                    this._getMessageContent(message)
                  );
                  logger.info("\u2705 Agent finished with output");
                }
              }
              if (shouldRestart) {
                break;
              }
            }
          }
          if (shouldRestart) {
            break;
          }
        }
        if (!shouldRestart) {
          break;
        }
        if (restartCount > maxRestarts) {
          logger.warn(
            `\u26A0\uFE0F Max restarts (${maxRestarts}) reached. Continuing with current tools.`
          );
          break;
        }
      }
      if (this.memoryEnabled) {
        const newMessages = accumulatedMessages.slice(langchainHistory.length);
        for (const msg of newMessages) {
          this.addToHistory(msg);
        }
      }
      if (schema && finalOutput) {
        try {
          logger.info("\u{1F527} Attempting structured output...");
          const structuredResult = await this._attemptStructuredOutput(
            finalOutput,
            this.llm,
            schema
          );
          if (this.memoryEnabled) {
            this.addToHistory(
              new import_langchain2.AIMessage(
                `Structured result: ${JSON.stringify(structuredResult)}`
              )
            );
          }
          logger.info("\u2705 Structured output successful");
          success = true;
          return structuredResult;
        } catch (e) {
          logger.error(`\u274C Structured output failed: ${e}`);
          throw new Error(
            `Failed to generate structured output: ${e instanceof Error ? e.message : String(e)}`
          );
        }
      }
      logger.info(
        `\u{1F389} Agent execution complete in ${((Date.now() - startTime) / 1e3).toFixed(2)} seconds`
      );
      success = true;
      return finalOutput || "No output generated";
    } catch (e) {
      logger.error(`\u274C Error running query: ${e}`);
      if (initializedHere && manage) {
        logger.info("\u{1F9F9} Cleaning up resources after error");
        await this.close();
      }
      throw e;
    } finally {
      const executionTimeMs = Date.now() - startTime;
      let serverCount = 0;
      if (this.client) {
        serverCount = Object.keys(this.client.getAllActiveSessions()).length;
      } else if (this.connectors) {
        serverCount = this.connectors.length;
      }
      const conversationHistoryLength = this.memoryEnabled ? this.conversationHistory.length : 0;
      const toolsAvailable = this._tools || [];
      await this.telemetry.trackAgentExecution({
        executionMethod: "stream",
        query,
        success,
        modelProvider: this.modelProvider,
        modelName: this.modelName,
        serverCount,
        serverIdentifiers: this.connectors.map(
          (connector) => connector.publicIdentifier
        ),
        totalToolsAvailable: toolsAvailable.length,
        toolsAvailableNames: toolsAvailable.map((t) => t.name),
        maxStepsConfigured: this.maxSteps,
        memoryEnabled: this.memoryEnabled,
        useServerManager: this.useServerManager,
        maxStepsUsed: steps ?? null,
        manageConnector: manage ?? true,
        externalHistoryUsed: history !== void 0,
        stepsTaken,
        toolsUsedCount: this.toolsUsedNames.length,
        toolsUsedNames: this.toolsUsedNames,
        response: finalOutput || "",
        executionTimeMs,
        errorType: success ? null : "execution_error",
        conversationHistoryLength
      });
      if (manage && !this.client && initializedHere) {
        logger.info("\u{1F9F9} Closing agent after stream completion");
        await this.close();
      }
    }
  }
  /**
   * Flush observability traces to the configured observability platform.
   * Important for serverless environments where traces need to be sent before function termination.
   */
  async flush() {
    if (this.isRemote && this.remoteAgent) {
      return;
    }
    logger.debug("Flushing observability traces...");
    await this.observabilityManager.flush();
  }
  async close() {
    if (this.isRemote && this.remoteAgent) {
      await this.remoteAgent.close();
      return;
    }
    logger.info("\u{1F50C} Closing MCPAgent resources\u2026");
    await this.observabilityManager.shutdown();
    try {
      this._agentExecutor = null;
      this._tools = [];
      if (this.client) {
        if (this.clientOwnedByAgent) {
          logger.info(
            "\u{1F504} Closing internally-created client (simplified mode) and cleaning up resources"
          );
          await this.client.close();
          this.sessions = {};
          this.client = void 0;
        } else {
          logger.info("\u{1F504} Closing client and cleaning up resources");
          await this.client.close();
          this.sessions = {};
        }
      } else {
        for (const connector of this.connectors) {
          logger.info("\u{1F504} Disconnecting connector");
          await connector.disconnect();
        }
      }
      if (this.isSimplifiedMode && this.llm) {
        logger.debug("\u{1F504} Clearing LLM reference (simplified mode)");
        this.llm = void 0;
      }
      if ("connectorToolMap" in this.adapter) {
        this.adapter = new LangChainAdapter();
      }
    } finally {
      this._initialized = false;
      logger.info("\u{1F44B} Agent closed successfully");
    }
  }
  async *prettyStreamEvents(queryOrOptions, maxSteps, manageConnector = true, externalHistory, outputSchema) {
    const { prettyStreamEvents: prettyStream } = await Promise.resolve().then(() => (init_display(), display_exports));
    const finalResponse = "";
    for await (const _ of prettyStream(
      this.streamEvents(
        queryOrOptions,
        maxSteps,
        manageConnector,
        externalHistory,
        outputSchema
      )
    )) {
      yield;
    }
    return finalResponse;
  }
  async *streamEvents(queryOrOptions, maxSteps, manageConnector = true, externalHistory, outputSchema) {
    const normalized = normalizeRunOptions(
      queryOrOptions,
      maxSteps,
      manageConnector,
      externalHistory,
      outputSchema
    );
    let { query } = normalized;
    const {
      maxSteps: steps,
      manageConnector: manage,
      externalHistory: history,
      outputSchema: schema
    } = normalized;
    let initializedHere = false;
    const startTime = Date.now();
    let success = false;
    let eventCount = 0;
    let totalResponseLength = 0;
    let finalResponse = "";
    if (schema) {
      query = this._enhanceQueryWithSchema(query, schema);
    }
    try {
      if (manage && !this._initialized) {
        await this.initialize();
        initializedHere = true;
      } else if (!this._initialized && this.autoInitialize) {
        await this.initialize();
        initializedHere = true;
      }
      const agentExecutor = this._agentExecutor;
      if (!agentExecutor) {
        throw new Error("MCP agent failed to initialize");
      }
      this.maxSteps = steps ?? this.maxSteps;
      const display_query = typeof query === "string" && query.length > 50 ? `${query.slice(0, 50).replace(/\n/g, " ")}...` : typeof query === "string" ? query.replace(/\n/g, " ") : String(query);
      logger.info(`\u{1F4AC} Received query for streamEvents: '${display_query}'`);
      if (this.memoryEnabled) {
        logger.info(`\u{1F504} Adding user message to history: ${display_query}`);
        this.addToHistory(new import_langchain2.HumanMessage({ content: query }));
      }
      const historyToUse = history ?? this.conversationHistory;
      const langchainHistory = [];
      for (const msg of historyToUse) {
        if (this._isHumanMessageLike(msg) || this._isAIMessageLike(msg) || this._isToolMessageLike(msg)) {
          langchainHistory.push(msg);
        } else {
          logger.info(
            `\u26A0\uFE0F Skipped message of type: ${msg.constructor?.name || typeof msg}`
          );
        }
      }
      const inputs = [
        ...langchainHistory,
        new import_langchain2.HumanMessage(query)
      ];
      logger.info("callbacks", this.callbacks);
      const eventStream = agentExecutor.streamEvents(
        { messages: inputs },
        {
          streamMode: "messages",
          version: "v2",
          callbacks: this.callbacks,
          metadata: this.getMetadata(),
          tags: this.getTags(),
          // Set trace name for LangChain/Langfuse
          runName: this.metadata.trace_name || "mcp-use-agent",
          // Set recursion limit to 3x maxSteps to account for model calls + tool executions
          recursionLimit: this.maxSteps * 3,
          // Pass sessionId for Langfuse if present in metadata
          ...this.metadata.session_id && {
            sessionId: this.metadata.session_id
          }
        }
      );
      for await (const event of eventStream) {
        eventCount++;
        if (!event || typeof event !== "object") {
          continue;
        }
        if (event.event === "on_chat_model_stream" && event.data?.chunk?.content) {
          totalResponseLength += event.data.chunk.content.length;
        }
        if (event.event === "on_chat_model_stream" && event.data?.chunk) {
          const chunk = event.data.chunk;
          if (chunk.content) {
            if (!finalResponse) {
              finalResponse = "";
            }
            const normalizedContent = this._normalizeOutput(chunk.content);
            finalResponse += normalizedContent;
            logger.debug(
              `\u{1F4DD} Accumulated response length: ${finalResponse.length}`
            );
          }
        }
        yield event;
        if (event.event === "on_chain_end" && event.data?.output && !finalResponse) {
          const output = event.data.output;
          if (Array.isArray(output) && output.length > 0 && output[0]?.text) {
            finalResponse = output[0].text;
          } else if (typeof output === "string") {
            finalResponse = output;
          } else if (output && typeof output === "object" && "output" in output) {
            finalResponse = output.output;
          }
        }
      }
      if (schema && finalResponse) {
        logger.info("\u{1F527} Attempting structured output conversion...");
        try {
          let conversionCompleted = false;
          let conversionResult = null;
          let conversionError = null;
          this._attemptStructuredOutput(finalResponse, this.llm, schema).then((result) => {
            conversionCompleted = true;
            conversionResult = result;
            return result;
          }).catch((error) => {
            conversionCompleted = true;
            conversionError = error;
            throw error;
          });
          let progressCount = 0;
          while (!conversionCompleted) {
            await new Promise((resolve) => setTimeout(resolve, 2e3));
            if (!conversionCompleted) {
              progressCount++;
              yield {
                event: "on_structured_output_progress",
                data: {
                  message: `Converting to structured output... (${progressCount * 2}s)`,
                  elapsed: progressCount * 2
                }
              };
            }
          }
          if (conversionError) {
            throw conversionError;
          }
          if (conversionResult) {
            yield {
              event: "on_structured_output",
              data: { output: conversionResult }
            };
            if (this.memoryEnabled) {
              this.addToHistory(
                new import_langchain2.AIMessage(
                  `Structured result: ${JSON.stringify(conversionResult)}`
                )
              );
            }
            logger.info("\u2705 Structured output successful");
          }
        } catch (e) {
          logger.warn(`\u26A0\uFE0F Structured output failed: ${e}`);
          yield {
            event: "on_structured_output_error",
            data: { error: e instanceof Error ? e.message : String(e) }
          };
        }
      } else if (this.memoryEnabled && finalResponse) {
        this.addToHistory(new import_langchain2.AIMessage(finalResponse));
      }
      console.log("\n\n");
      logger.info(`\u{1F389} StreamEvents complete - ${eventCount} events emitted`);
      success = true;
    } catch (e) {
      logger.error(`\u274C Error during streamEvents: ${e}`);
      if (initializedHere && manage) {
        logger.info(
          "\u{1F9F9} Cleaning up resources after initialization error in streamEvents"
        );
        await this.close();
      }
      throw e;
    } finally {
      const executionTimeMs = Date.now() - startTime;
      let serverCount = 0;
      if (this.client) {
        serverCount = Object.keys(this.client.getAllActiveSessions()).length;
      } else if (this.connectors) {
        serverCount = this.connectors.length;
      }
      const conversationHistoryLength = this.memoryEnabled ? this.conversationHistory.length : 0;
      await this.telemetry.trackAgentExecution({
        executionMethod: "streamEvents",
        query,
        success,
        modelProvider: this.modelProvider,
        modelName: this.modelName,
        serverCount,
        serverIdentifiers: this.connectors.map(
          (connector) => connector.publicIdentifier
        ),
        totalToolsAvailable: this._tools.length,
        toolsAvailableNames: this._tools.map((t) => t.name),
        maxStepsConfigured: this.maxSteps,
        memoryEnabled: this.memoryEnabled,
        useServerManager: this.useServerManager,
        maxStepsUsed: steps ?? null,
        manageConnector: manage ?? true,
        externalHistoryUsed: history !== void 0,
        response: `[STREAMED RESPONSE - ${totalResponseLength} chars]`,
        executionTimeMs,
        errorType: success ? null : "streaming_error",
        conversationHistoryLength
      });
      if (manage && !this.client && initializedHere) {
        logger.info("\u{1F9F9} Closing agent after streamEvents completion");
        await this.close();
      }
    }
  }
  /**
   * Attempt to create structured output from raw result with validation and retry logic.
   *
   * @param rawResult - The raw text result from the agent
   * @param llm - LLM to use for structured output
   * @param outputSchema - The Zod schema to validate against
   */
  async _attemptStructuredOutput(rawResult, llm, outputSchema) {
    logger.info(
      `\u{1F504} Attempting structured output with schema: ${JSON.stringify(outputSchema, null, 2)}`
    );
    logger.info(`\u{1F504} Raw result: ${JSON.stringify(rawResult, null, 2)}`);
    let structuredLlm = null;
    let schemaDescription = "";
    logger.debug(
      `\u{1F504} Structured output requested, schema: ${JSON.stringify((0, import_zod9.toJSONSchema)(outputSchema), null, 2)}`
    );
    if (llm && "withStructuredOutput" in llm && typeof llm.withStructuredOutput === "function") {
      structuredLlm = llm.withStructuredOutput(outputSchema);
    } else if (llm) {
      structuredLlm = llm;
    } else {
      throw new Error("LLM is required for structured output");
    }
    const jsonSchema = (0, import_zod9.toJSONSchema)(outputSchema);
    const { $schema, additionalProperties, ...cleanSchema } = jsonSchema;
    schemaDescription = JSON.stringify(cleanSchema, null, 2);
    logger.info(`\u{1F504} Schema description: ${schemaDescription}`);
    let textContent = "";
    if (typeof rawResult === "string") {
      textContent = rawResult;
    } else if (rawResult && typeof rawResult === "object") {
      textContent = JSON.stringify(rawResult);
    }
    logger.info("rawResult", rawResult);
    if (!textContent) {
      textContent = JSON.stringify(rawResult);
    }
    const maxRetries = 3;
    let lastError = "";
    for (let attempt = 1; attempt <= maxRetries; attempt++) {
      logger.info(`\u{1F504} Structured output attempt ${attempt}/${maxRetries}`);
      let formatPrompt = `
      Please format the following information according to the EXACT schema specified below.
      You must use the exact field names and types as shown in the schema.

      Required schema format:
      ${schemaDescription}

      Content to extract from:
      ${textContent}

      IMPORTANT:
      - Use ONLY the field names specified in the schema
      - Match the data types exactly (string, number, boolean, array, etc.)
      - Include ALL required fields
      - Return valid JSON that matches the schema structure exactly
      - For missing data: use null for nullable fields, omit optional fields entirely
      - Do NOT use empty strings ("") or zero (0) as placeholders for missing data
      `;
      if (attempt > 1) {
        formatPrompt += `

        PREVIOUS ATTEMPT FAILED with error: ${lastError}
        Please fix the issues mentioned above and ensure the output matches the schema exactly.
        `;
      }
      try {
        logger.info(
          `\u{1F504} Structured output attempt ${attempt} - using streaming approach`
        );
        const contentPreview = textContent.length > 300 ? `${textContent.slice(0, 300)}...` : textContent;
        logger.info(
          `\u{1F504} Content being formatted (${textContent.length} chars): ${contentPreview}`
        );
        logger.info(
          `\u{1F504} Full format prompt (${formatPrompt.length} chars):
${formatPrompt}`
        );
        const stream = await structuredLlm.stream(formatPrompt);
        let structuredResult = null;
        let chunkCount = 0;
        for await (const chunk of stream) {
          chunkCount++;
          logger.debug(
            `Chunk ${chunkCount}: ${JSON.stringify(chunk, null, 2)}`
          );
          if (typeof chunk === "string") {
            try {
              structuredResult = JSON.parse(chunk);
            } catch (e) {
              logger.warn(`\u{1F504} Failed to parse string chunk as JSON: ${chunk}`);
            }
          } else if (chunk && typeof chunk === "object") {
            structuredResult = chunk;
          } else {
            try {
              structuredResult = JSON.parse(String(chunk));
            } catch (e) {
              logger.warn(`\u{1F504} Failed to parse chunk as JSON: ${chunk}`);
            }
          }
          if (chunkCount % 10 === 0) {
            logger.debug(
              `\u{1F504} Structured output streaming: ${chunkCount} chunks`
            );
          }
        }
        logger.info(
          `\u{1F504} Structured result attempt ${attempt}: ${JSON.stringify(structuredResult, null, 2)}`
        );
        if (!structuredResult) {
          throw new Error("No structured result received from stream");
        }
        const validatedResult = this._validateStructuredResult(
          structuredResult,
          outputSchema
        );
        logger.info(`\u2705 Structured output successful on attempt ${attempt}`);
        return validatedResult;
      } catch (e) {
        lastError = e instanceof Error ? e.message : String(e);
        logger.warn(
          `\u26A0\uFE0F Structured output attempt ${attempt} failed: ${lastError}`
        );
        if (attempt === maxRetries) {
          logger.error(
            `\u274C All ${maxRetries} structured output attempts failed`
          );
          throw new Error(
            `Failed to generate valid structured output after ${maxRetries} attempts. Last error: ${lastError}`
          );
        }
        continue;
      }
    }
    throw new Error("Unexpected error in structured output generation");
  }
  /**
   * Validate the structured result against the schema with detailed error reporting
   */
  _validateStructuredResult(structuredResult, outputSchema) {
    try {
      const validatedResult = outputSchema.parse(structuredResult);
      const schemaType = outputSchema;
      if (schemaType._def && schemaType._def.shape) {
        for (const [fieldName, fieldSchema] of Object.entries(
          schemaType._def.shape
        )) {
          const field = fieldSchema;
          const isOptional = field.isOptional?.() ?? field._def?.typeName === "ZodOptional";
          const isNullable = field.isNullable?.() ?? field._def?.typeName === "ZodNullable";
          if (!isOptional && !isNullable) {
            const value = validatedResult[fieldName];
            if (value === null || value === void 0 || typeof value === "string" && !value.trim() || Array.isArray(value) && value.length === 0) {
              throw new Error(
                `Required field '${fieldName}' is missing or empty`
              );
            }
          }
        }
      }
      return validatedResult;
    } catch (e) {
      logger.debug(`Validation details: ${e}`);
      throw e;
    }
  }
  /**
   * Enhance the query with schema information to make the agent aware of required fields.
   */
  _enhanceQueryWithSchema(query, outputSchema) {
    try {
      const jsonSchema = (0, import_zod9.toJSONSchema)(outputSchema);
      const { $schema, additionalProperties, ...cleanSchema } = jsonSchema;
      const schemaDescription = JSON.stringify(cleanSchema, null, 2);
      const enhancedQuery = `
      ${query}

      IMPORTANT: Your response must include sufficient information to populate the following structured output:

      ${schemaDescription}

      Make sure you gather ALL the required information during your task execution.
      If any required information is missing, continue working to find it.
      `;
      return enhancedQuery;
    } catch (e) {
      logger.warn(`Could not extract schema details: ${e}`);
      return query;
    }
  }
};

// index.ts
init_client();
init_config();
init_base3();
init_http();
init_stdio2();
init_logging();
init_session();

// src/agents/utils/ai_sdk.ts
async function* streamEventsToAISDK(streamEvents) {
  for await (const event of streamEvents) {
    if (event.event === "on_chat_model_stream" && event.data?.chunk?.text) {
      const textContent = event.data.chunk.text;
      if (typeof textContent === "string" && textContent.length > 0) {
        yield textContent;
      }
    }
  }
}
__name(streamEventsToAISDK, "streamEventsToAISDK");
function createReadableStreamFromGenerator(generator) {
  return new ReadableStream({
    async start(controller) {
      try {
        for await (const chunk of generator) {
          controller.enqueue(chunk);
        }
        controller.close();
      } catch (error) {
        controller.error(error);
      }
    }
  });
}
__name(createReadableStreamFromGenerator, "createReadableStreamFromGenerator");
async function* streamEventsToAISDKWithTools(streamEvents) {
  for await (const event of streamEvents) {
    switch (event.event) {
      case "on_chat_model_stream":
        if (event.data?.chunk?.text) {
          const textContent = event.data.chunk.text;
          if (typeof textContent === "string" && textContent.length > 0) {
            yield textContent;
          }
        }
        break;
      case "on_tool_start":
        yield `
\u{1F527} Using tool: ${event.name}
`;
        break;
      case "on_tool_end":
        yield `
\u2705 Tool completed: ${event.name}
`;
        break;
      default:
        break;
    }
  }
}
__name(streamEventsToAISDKWithTools, "streamEventsToAISDKWithTools");

// index.ts
init_telemetry();
init_version();

// src/utils/url-sanitize.ts
function sanitizeUrl(raw) {
  const abort = /* @__PURE__ */ __name(() => {
    throw new Error(`Invalid url to pass to open(): ${raw}`);
  }, "abort");
  let url;
  try {
    url = new URL(raw);
  } catch (_) {
    abort();
  }
  if (url.protocol !== "https:" && url.protocol !== "http:") abort();
  if (url.hostname !== encodeURIComponent(url.hostname)) abort();
  if (url.username) url.username = encodeURIComponent(url.username);
  if (url.password) url.password = encodeURIComponent(url.password);
  url.pathname = url.pathname.slice(0, 1) + encodeURIComponent(url.pathname.slice(1)).replace(/%2f/gi, "/");
  url.search = url.search.slice(0, 1) + Array.from(url.searchParams.entries()).map(sanitizeParam).join("&");
  url.hash = url.hash.slice(0, 1) + encodeURIComponent(url.hash.slice(1));
  return url.href;
}
__name(sanitizeUrl, "sanitizeUrl");
function sanitizeParam([k, v]) {
  return `${encodeURIComponent(k)}${v.length > 0 ? `=${encodeURIComponent(v)}` : ""}`;
}
__name(sanitizeParam, "sanitizeParam");

// src/auth/browser-provider.ts
var BrowserOAuthClientProvider = class {
  static {
    __name(this, "BrowserOAuthClientProvider");
  }
  serverUrl;
  storageKeyPrefix;
  serverUrlHash;
  clientName;
  clientUri;
  logoUri;
  callbackUrl;
  preventAutoAuth;
  useRedirectFlow;
  onPopupWindow;
  constructor(serverUrl, options = {}) {
    this.serverUrl = serverUrl;
    this.storageKeyPrefix = options.storageKeyPrefix || "mcp:auth";
    this.serverUrlHash = this.hashString(serverUrl);
    this.clientName = options.clientName || "mcp-use";
    this.clientUri = options.clientUri || (typeof window !== "undefined" ? window.location.origin : "");
    this.logoUri = options.logoUri || "https://mcp-use.com/logo.png";
    this.callbackUrl = sanitizeUrl(
      options.callbackUrl || (typeof window !== "undefined" ? new URL("/oauth/callback", window.location.origin).toString() : "/oauth/callback")
    );
    this.preventAutoAuth = options.preventAutoAuth;
    this.useRedirectFlow = options.useRedirectFlow;
    this.onPopupWindow = options.onPopupWindow;
  }
  // --- SDK Interface Methods ---
  get redirectUrl() {
    return sanitizeUrl(this.callbackUrl);
  }
  get clientMetadata() {
    return {
      redirect_uris: [this.redirectUrl],
      token_endpoint_auth_method: "none",
      // Public client
      grant_types: ["authorization_code", "refresh_token"],
      response_types: ["code"],
      client_name: this.clientName,
      client_uri: this.clientUri,
      logo_uri: this.logoUri
      // scope: 'openid profile email mcp', // Example scopes, adjust as needed
    };
  }
  async clientInformation() {
    const key = this.getKey("client_info");
    const data = localStorage.getItem(key);
    if (!data) return void 0;
    try {
      return JSON.parse(data);
    } catch (e) {
      console.warn(
        `[${this.storageKeyPrefix}] Failed to parse client information:`,
        e
      );
      localStorage.removeItem(key);
      return void 0;
    }
  }
  // NOTE: The SDK's auth() function uses this if dynamic registration is needed.
  // Ensure your OAuthClientInformationFull matches the expected structure if DCR is used.
  async saveClientInformation(clientInformation) {
    const key = this.getKey("client_info");
    localStorage.setItem(key, JSON.stringify(clientInformation));
  }
  async tokens() {
    const key = this.getKey("tokens");
    const data = localStorage.getItem(key);
    if (!data) return void 0;
    try {
      return JSON.parse(data);
    } catch (e) {
      console.warn(`[${this.storageKeyPrefix}] Failed to parse tokens:`, e);
      localStorage.removeItem(key);
      return void 0;
    }
  }
  async saveTokens(tokens) {
    const key = this.getKey("tokens");
    localStorage.setItem(key, JSON.stringify(tokens));
    localStorage.removeItem(this.getKey("code_verifier"));
    localStorage.removeItem(this.getKey("last_auth_url"));
  }
  async saveCodeVerifier(codeVerifier) {
    const key = this.getKey("code_verifier");
    localStorage.setItem(key, codeVerifier);
  }
  async codeVerifier() {
    const key = this.getKey("code_verifier");
    const verifier = localStorage.getItem(key);
    if (!verifier) {
      throw new Error(
        `[${this.storageKeyPrefix}] Code verifier not found in storage for key ${key}. Auth flow likely corrupted or timed out.`
      );
    }
    return verifier;
  }
  /**
   * Generates and stores the authorization URL with state, without opening a popup.
   * Used when preventAutoAuth is enabled to provide the URL for manual navigation.
   * @param authorizationUrl The fully constructed authorization URL from the SDK.
   * @returns The full authorization URL with state parameter.
   */
  async prepareAuthorizationUrl(authorizationUrl) {
    const state = globalThis.crypto.randomUUID();
    const stateKey = `${this.storageKeyPrefix}:state_${state}`;
    const stateData = {
      serverUrlHash: this.serverUrlHash,
      expiry: Date.now() + 1e3 * 60 * 10,
      // State expires in 10 minutes
      // Store provider options needed to reconstruct on callback
      providerOptions: {
        serverUrl: this.serverUrl,
        storageKeyPrefix: this.storageKeyPrefix,
        clientName: this.clientName,
        clientUri: this.clientUri,
        callbackUrl: this.callbackUrl
      },
      // Store flow type so callback knows how to handle the response
      flowType: this.useRedirectFlow ? "redirect" : "popup",
      // Store current URL for redirect flow so we can return to it
      returnUrl: this.useRedirectFlow && typeof window !== "undefined" ? window.location.href : void 0
    };
    localStorage.setItem(stateKey, JSON.stringify(stateData));
    authorizationUrl.searchParams.set("state", state);
    const authUrlString = authorizationUrl.toString();
    const sanitizedAuthUrl = sanitizeUrl(authUrlString);
    localStorage.setItem(this.getKey("last_auth_url"), sanitizedAuthUrl);
    return sanitizedAuthUrl;
  }
  /**
   * Redirects the user agent to the authorization URL, storing necessary state.
   * This now adheres to the SDK's void return type expectation for the interface.
   * @param authorizationUrl The fully constructed authorization URL from the SDK.
   */
  async redirectToAuthorization(authorizationUrl) {
    const sanitizedAuthUrl = await this.prepareAuthorizationUrl(authorizationUrl);
    if (this.preventAutoAuth) {
      console.info(
        `[${this.storageKeyPrefix}] Auto-auth prevented. Authorization URL stored for manual trigger.`
      );
      return;
    }
    if (this.useRedirectFlow) {
      console.info(
        `[${this.storageKeyPrefix}] Redirecting to authorization URL (full-page redirect).`
      );
      window.location.href = sanitizedAuthUrl;
      return;
    }
    const popupFeatures = "width=600,height=700,resizable=yes,scrollbars=yes,status=yes";
    try {
      const popup = window.open(
        sanitizedAuthUrl,
        `mcp_auth_${this.serverUrlHash}`,
        popupFeatures
      );
      if (this.onPopupWindow) {
        this.onPopupWindow(sanitizedAuthUrl, popupFeatures, popup);
      }
      if (!popup || popup.closed || typeof popup.closed === "undefined") {
        console.warn(
          `[${this.storageKeyPrefix}] Popup likely blocked by browser. Manual navigation might be required using the stored URL.`
        );
      } else {
        popup.focus();
        console.info(
          `[${this.storageKeyPrefix}] Redirecting to authorization URL in popup.`
        );
      }
    } catch (e) {
      console.error(
        `[${this.storageKeyPrefix}] Error opening popup window:`,
        e
      );
    }
  }
  // --- Helper Methods ---
  /**
   * Retrieves the last URL passed to `redirectToAuthorization`. Useful for manual fallback.
   */
  getLastAttemptedAuthUrl() {
    const storedUrl = localStorage.getItem(this.getKey("last_auth_url"));
    return storedUrl ? sanitizeUrl(storedUrl) : null;
  }
  clearStorage() {
    const prefixPattern = `${this.storageKeyPrefix}_${this.serverUrlHash}_`;
    const statePattern = `${this.storageKeyPrefix}:state_`;
    const keysToRemove = [];
    let count = 0;
    for (let i = 0; i < localStorage.length; i++) {
      const key = localStorage.key(i);
      if (!key) continue;
      if (key.startsWith(prefixPattern)) {
        keysToRemove.push(key);
      } else if (key.startsWith(statePattern)) {
        try {
          const item = localStorage.getItem(key);
          if (item) {
            const state = JSON.parse(item);
            if (state.serverUrlHash === this.serverUrlHash) {
              keysToRemove.push(key);
            }
          }
        } catch (e) {
          console.warn(
            `[${this.storageKeyPrefix}] Error parsing state key ${key} during clearStorage:`,
            e
          );
        }
      }
    }
    const uniqueKeysToRemove = [...new Set(keysToRemove)];
    uniqueKeysToRemove.forEach((key) => {
      localStorage.removeItem(key);
      count++;
    });
    return count;
  }
  hashString(str) {
    let hash = 0;
    for (let i = 0; i < str.length; i++) {
      const char = str.charCodeAt(i);
      hash = (hash << 5) - hash + char;
      hash = hash & hash;
    }
    return Math.abs(hash).toString(16);
  }
  getKey(keySuffix) {
    return `${this.storageKeyPrefix}_${this.serverUrlHash}_${keySuffix}`;
  }
};

// src/auth/callback.ts
var import_auth = require("@modelcontextprotocol/sdk/client/auth.js");
async function onMcpAuthorization() {
  const queryParams = new URLSearchParams(window.location.search);
  const code = queryParams.get("code");
  const state = queryParams.get("state");
  const error = queryParams.get("error");
  const errorDescription = queryParams.get("error_description");
  const logPrefix = "[mcp-callback]";
  console.log(`${logPrefix} Handling callback...`, {
    code,
    state,
    error,
    errorDescription
  });
  let provider = null;
  let storedStateData = null;
  const stateKey = state ? `mcp:auth:state_${state}` : null;
  try {
    if (error) {
      throw new Error(
        `OAuth error: ${error} - ${errorDescription || "No description provided."}`
      );
    }
    if (!code) {
      throw new Error(
        "Authorization code not found in callback query parameters."
      );
    }
    if (!state || !stateKey) {
      throw new Error(
        "State parameter not found or invalid in callback query parameters."
      );
    }
    const storedStateJSON = localStorage.getItem(stateKey);
    if (!storedStateJSON) {
      throw new Error(
        `Invalid or expired state parameter "${state}". No matching state found in storage.`
      );
    }
    try {
      storedStateData = JSON.parse(storedStateJSON);
    } catch (e) {
      throw new Error("Failed to parse stored OAuth state.");
    }
    if (!storedStateData.expiry || storedStateData.expiry < Date.now()) {
      localStorage.removeItem(stateKey);
      throw new Error(
        "OAuth state has expired. Please try initiating authentication again."
      );
    }
    if (!storedStateData.providerOptions) {
      throw new Error("Stored state is missing required provider options.");
    }
    const { serverUrl, ...providerOptions } = storedStateData.providerOptions;
    console.log(
      `${logPrefix} Re-instantiating provider for server: ${serverUrl}`
    );
    provider = new BrowserOAuthClientProvider(serverUrl, providerOptions);
    console.log(`${logPrefix} Calling SDK auth() to exchange code...`);
    const baseUrl = new URL(serverUrl).origin;
    const authResult = await (0, import_auth.auth)(provider, {
      serverUrl: baseUrl,
      authorizationCode: code
    });
    if (authResult === "AUTHORIZED") {
      console.log(`${logPrefix} Authorization successful via SDK auth().`);
      const isRedirectFlow = storedStateData.flowType === "redirect";
      if (isRedirectFlow && storedStateData.returnUrl) {
        console.log(
          `${logPrefix} Redirect flow complete. Returning to: ${storedStateData.returnUrl}`
        );
        localStorage.removeItem(stateKey);
        window.location.href = storedStateData.returnUrl;
      } else if (window.opener && !window.opener.closed) {
        console.log(`${logPrefix} Popup flow complete. Notifying opener...`);
        window.opener.postMessage(
          { type: "mcp_auth_callback", success: true },
          window.location.origin
        );
        localStorage.removeItem(stateKey);
        window.close();
      } else {
        console.warn(
          `${logPrefix} No opener window or return URL detected. Redirecting to root.`
        );
        localStorage.removeItem(stateKey);
        const pathParts = window.location.pathname.split("/").filter(Boolean);
        const basePath = pathParts.length > 0 && pathParts[pathParts.length - 1] === "callback" ? "/" + pathParts.slice(0, -2).join("/") : "/";
        window.location.href = basePath || "/";
      }
    } else {
      console.warn(
        `${logPrefix} SDK auth() returned unexpected status: ${authResult}`
      );
      throw new Error(
        `Unexpected result from authentication library: ${authResult}`
      );
    }
  } catch (err) {
    console.error(`${logPrefix} Error during OAuth callback handling:`, err);
    const errorMessage = err instanceof Error ? err.message : String(err);
    if (window.opener && !window.opener.closed) {
      window.opener.postMessage(
        { type: "mcp_auth_callback", success: false, error: errorMessage },
        window.location.origin
      );
    }
    try {
      document.body.innerHTML = "";
      const container = document.createElement("div");
      container.style.fontFamily = "sans-serif";
      container.style.padding = "20px";
      const heading = document.createElement("h1");
      heading.textContent = "Authentication Error";
      container.appendChild(heading);
      const errorPara = document.createElement("p");
      errorPara.style.color = "red";
      errorPara.style.backgroundColor = "#ffebeb";
      errorPara.style.border = "1px solid red";
      errorPara.style.padding = "10px";
      errorPara.style.borderRadius = "4px";
      errorPara.textContent = errorMessage;
      container.appendChild(errorPara);
      const closePara = document.createElement("p");
      closePara.textContent = "You can close this window or ";
      const closeLink = document.createElement("a");
      closeLink.href = "#";
      closeLink.textContent = "click here to close";
      closeLink.onclick = (e) => {
        e.preventDefault();
        window.close();
        return false;
      };
      closePara.appendChild(closeLink);
      closePara.appendChild(document.createTextNode("."));
      container.appendChild(closePara);
      if (err instanceof Error && err.stack) {
        const stackPre = document.createElement("pre");
        stackPre.style.fontSize = "0.8em";
        stackPre.style.color = "#555";
        stackPre.style.marginTop = "20px";
        stackPre.style.whiteSpace = "pre-wrap";
        stackPre.textContent = err.stack;
        container.appendChild(stackPre);
      }
      document.body.appendChild(container);
    } catch (displayError) {
      console.error(
        `${logPrefix} Could not display error in callback window:`,
        displayError
      );
    }
    if (stateKey) {
      localStorage.removeItem(stateKey);
    }
    if (provider) {
      localStorage.removeItem(provider.getKey("code_verifier"));
      localStorage.removeItem(provider.getKey("last_auth_url"));
    }
  }
}
__name(onMcpAuthorization, "onMcpAuthorization");

// src/react/useMcp.ts
var import_react = require("react");

// src/client/browser.ts
init_http();
init_logging();
init_telemetry_browser();
init_version();
init_base();
var BrowserMCPClient = class _BrowserMCPClient extends BaseMCPClient {
  static {
    __name(this, "BrowserMCPClient");
  }
  /**
   * Get the mcp-use package version.
   * Works in all environments (Node.js, browser, Cloudflare Workers, Deno, etc.)
   */
  static getPackageVersion() {
    return getPackageVersion();
  }
  constructor(config) {
    super(config);
    this._trackClientInit();
  }
  _trackClientInit() {
    const servers = Object.keys(this.config.mcpServers ?? {});
    Tel.getInstance().trackMCPClientInit({
      codeMode: false,
      // Browser client doesn't support code mode
      sandbox: false,
      // Sandbox not supported in browser
      allCallbacks: false,
      // Will be set per-server
      verify: false,
      servers,
      numServers: servers.length,
      isBrowser: true
      // Browser MCPClient
    }).catch(
      (e) => logger.debug(`Failed to track BrowserMCPClient init: ${e}`)
    );
  }
  static fromDict(cfg) {
    return new _BrowserMCPClient(cfg);
  }
  /**
   * Create a connector from server configuration (Browser version)
   * Supports HTTP connector only
   */
  createConnectorFromConfig(serverConfig) {
    const {
      url,
      headers,
      authToken,
      authProvider,
      wrapTransport,
      clientOptions,
      samplingCallback,
      elicitationCallback,
      disableSseFallback,
      preferSse,
      clientInfo
    } = serverConfig;
    if (!url) {
      throw new Error("Server URL is required");
    }
    const connectorOptions = {
      headers,
      authToken,
      authProvider,
      // ← Pass OAuth provider to connector
      wrapTransport,
      // ← Pass transport wrapper if provided
      clientOptions,
      // ← Pass client options (capabilities, etc.) to connector
      samplingCallback,
      // ← Pass sampling callback to connector
      elicitationCallback,
      // ← Pass elicitation callback to connector
      disableSseFallback,
      // ← Disable automatic SSE fallback
      preferSse,
      // ← Use SSE transport directly
      clientInfo
      // ← Pass client info (name, version) to connector
    };
    if (clientOptions) {
      console.log(
        "[BrowserMCPClient] Passing clientOptions to connector:",
        JSON.stringify(clientOptions, null, 2)
      );
    } else {
      console.warn(
        "[BrowserMCPClient] No clientOptions provided to connector!"
      );
    }
    return new HttpConnector(url, connectorOptions);
  }
};

// src/react/useMcp.ts
init_telemetry_browser();

// src/utils/assert.ts
function assert(condition, message) {
  if (!condition) {
    throw new Error(message);
  }
}
__name(assert, "assert");

// src/utils/favicon-detector.ts
function isLocalServer(domain) {
  return domain === "localhost" || domain === "127.0.0.1" || domain.startsWith("127.") || domain.startsWith("192.168.") || domain.startsWith("10.") || domain.startsWith("172.");
}
__name(isLocalServer, "isLocalServer");
function getBaseDomain(hostname) {
  const parts = hostname.split(".");
  if (parts.length <= 2) {
    return hostname;
  }
  return parts.slice(parts.length - 2).join(".");
}
__name(getBaseDomain, "getBaseDomain");
function blobToBase64(blob) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onloadend = () => {
      resolve(reader.result);
    };
    reader.onerror = reject;
    reader.readAsDataURL(blob);
  });
}
__name(blobToBase64, "blobToBase64");
async function detectFavicon(serverUrl) {
  try {
    let domain;
    if (serverUrl.startsWith("http://") || serverUrl.startsWith("https://")) {
      domain = new URL(serverUrl).hostname;
    } else if (serverUrl.includes("://")) {
      domain = serverUrl.split("://")[1].split("/")[0];
    } else {
      domain = serverUrl.split("/")[0];
    }
    if (isLocalServer(domain)) {
      return null;
    }
    const baseDomain = getBaseDomain(domain);
    const domainsToTry = domain !== baseDomain ? [domain, baseDomain] : [domain];
    for (const currentDomain of domainsToTry) {
      try {
        const faviconApiUrl = `https://favicon.tools.mcp-use.com/${currentDomain}`;
        const controller = new AbortController();
        const timeoutId = setTimeout(() => controller.abort(), 2e3);
        try {
          const response = await fetch(faviconApiUrl, {
            signal: controller.signal
          });
          clearTimeout(timeoutId);
          if (!response.ok) {
            continue;
          }
          const blob = await response.blob();
          const base64Image = await blobToBase64(blob);
          return base64Image;
        } catch (err) {
          clearTimeout(timeoutId);
          continue;
        }
      } catch (error) {
        continue;
      }
    }
    return null;
  } catch (error) {
    console.warn("[favicon-detector] Error detecting favicon:", error);
    return null;
  }
}
__name(detectFavicon, "detectFavicon");

// src/utils/proxy-config.ts
function applyProxyConfig(originalUrl, proxyConfig) {
  if (!proxyConfig?.proxyAddress) {
    return {
      url: originalUrl,
      headers: proxyConfig?.customHeaders || {}
    };
  }
  const proxyUrl = new URL(proxyConfig.proxyAddress);
  const targetUrl = new URL(originalUrl);
  const finalUrl = `${proxyUrl.origin}${proxyUrl.pathname}${targetUrl.pathname}${targetUrl.search}`;
  const headers = {
    "X-Target-URL": originalUrl,
    ...proxyConfig.customHeaders
  };
  return { url: finalUrl, headers };
}
__name(applyProxyConfig, "applyProxyConfig");

// src/react/useMcp.ts
init_version();
var DEFAULT_RECONNECT_DELAY = 3e3;
var DEFAULT_RETRY_DELAY = 5e3;
function useMcp(options) {
  const {
    url,
    enabled = true,
    callbackUrl = typeof window !== "undefined" ? sanitizeUrl(
      new URL("/oauth/callback", window.location.origin).toString()
    ) : "/oauth/callback",
    storageKeyPrefix = "mcp:auth",
    clientConfig = {},
    customHeaders = {},
    proxyConfig,
    debug: _debug = false,
    autoRetry = false,
    autoReconnect = DEFAULT_RECONNECT_DELAY,
    transportType = "auto",
    preventAutoAuth = false,
    // Default to false for backward compatibility (auto-trigger OAuth)
    useRedirectFlow = false,
    // Default to false for backward compatibility (use popup)
    onPopupWindow,
    timeout = 3e4,
    // 30 seconds default for connection timeout
    sseReadTimeout = 3e5,
    // 5 minutes default for SSE read timeout
    wrapTransport,
    onNotification,
    samplingCallback,
    onElicitation
  } = options;
  const { url: finalUrl, headers: proxyHeaders } = (0, import_react.useMemo)(
    () => applyProxyConfig(url || "", proxyConfig),
    [url, proxyConfig]
  );
  const allHeaders = (0, import_react.useMemo)(
    () => ({ ...proxyHeaders, ...customHeaders }),
    [proxyHeaders, customHeaders]
  );
  const [state, setState] = (0, import_react.useState)("discovering");
  const [tools, setTools] = (0, import_react.useState)([]);
  const [resources, setResources] = (0, import_react.useState)([]);
  const [resourceTemplates, setResourceTemplates] = (0, import_react.useState)([]);
  const [prompts, setPrompts] = (0, import_react.useState)([]);
  const [serverInfo, setServerInfo] = (0, import_react.useState)();
  const [capabilities, setCapabilities] = (0, import_react.useState)();
  const [error, setError] = (0, import_react.useState)(void 0);
  const [log, setLog] = (0, import_react.useState)([]);
  const [authUrl, setAuthUrl] = (0, import_react.useState)(void 0);
  const [authTokens, setAuthTokens] = (0, import_react.useState)(void 0);
  const clientRef = (0, import_react.useRef)(null);
  const authProviderRef = (0, import_react.useRef)(null);
  const iconLoadingPromiseRef = (0, import_react.useRef)(null);
  const connectingRef = (0, import_react.useRef)(false);
  const isMountedRef = (0, import_react.useRef)(true);
  const connectAttemptRef = (0, import_react.useRef)(0);
  const authTimeoutRef = (0, import_react.useRef)(null);
  const retryScheduledRef = (0, import_react.useRef)(false);
  const stateRef = (0, import_react.useRef)(state);
  const autoReconnectRef = (0, import_react.useRef)(autoReconnect);
  const successfulTransportRef = (0, import_react.useRef)(null);
  const connectRef = (0, import_react.useRef)(null);
  const failConnectionRef = (0, import_react.useRef)(null);
  (0, import_react.useEffect)(() => {
    stateRef.current = state;
    autoReconnectRef.current = autoReconnect;
  }, [state, autoReconnect]);
  const addLog = (0, import_react.useCallback)(
    (level, message, ...args) => {
      const fullMessage = args.length > 0 ? `${message} ${args.map((arg) => JSON.stringify(arg)).join(" ")}` : message;
      console[level](`[useMcp] ${fullMessage}`);
      if (isMountedRef.current) {
        setLog((prevLog) => [
          ...prevLog.slice(-100),
          { level, message: fullMessage, timestamp: Date.now() }
        ]);
      }
    },
    []
  );
  const disconnect = (0, import_react.useCallback)(
    async (quiet = false) => {
      if (!quiet) addLog("info", "Disconnecting...");
      connectingRef.current = false;
      if (authTimeoutRef.current) clearTimeout(authTimeoutRef.current);
      authTimeoutRef.current = null;
      if (clientRef.current) {
        try {
          const serverName = "inspector-server";
          const session = clientRef.current.getSession(serverName);
          if (session && session._healthCheckCleanup) {
            session._healthCheckCleanup();
            session._healthCheckCleanup = null;
          }
          await clientRef.current.closeSession(serverName);
        } catch (err) {
          if (!quiet) addLog("warn", "Error closing session:", err);
        }
      }
      clientRef.current = null;
      if (isMountedRef.current && !quiet) {
        setState("discovering");
        setTools([]);
        setResources([]);
        setResourceTemplates([]);
        setPrompts([]);
        setError(void 0);
        setAuthUrl(void 0);
      }
    },
    [addLog]
  );
  const failConnection = (0, import_react.useCallback)(
    (errorMessage, connectionError) => {
      addLog("error", errorMessage, connectionError ?? "");
      if (isMountedRef.current) {
        setState("failed");
        setError(errorMessage);
        const manualUrl = authProviderRef.current?.getLastAttemptedAuthUrl();
        if (manualUrl) {
          setAuthUrl(manualUrl);
          addLog(
            "info",
            "Manual authentication URL may be available.",
            manualUrl
          );
        }
      }
      connectingRef.current = false;
      if (url) {
        Tel.getInstance().trackUseMcpConnection({
          url,
          transportType,
          success: false,
          errorType: connectionError?.name || "UnknownError",
          hasOAuth: !!authProviderRef.current,
          hasSampling: !!samplingCallback,
          hasElicitation: !!onElicitation
        }).catch(() => {
        });
      }
    },
    [addLog, url, transportType, samplingCallback, onElicitation]
  );
  const connect = (0, import_react.useCallback)(async () => {
    if (!enabled || !url) {
      addLog(
        "debug",
        enabled ? "No server URL provided, skipping connection." : "Connection disabled via enabled flag."
      );
      return;
    }
    if (connectingRef.current) {
      addLog("debug", "Connection attempt already in progress.");
      return;
    }
    if (!isMountedRef.current) {
      addLog("debug", "Connect called after unmount, aborting.");
      return;
    }
    connectingRef.current = true;
    connectAttemptRef.current += 1;
    setError(void 0);
    setAuthUrl(void 0);
    successfulTransportRef.current = null;
    setState("discovering");
    addLog(
      "info",
      `Connecting attempt #${connectAttemptRef.current} to ${url}...`
    );
    if (!authProviderRef.current) {
      authProviderRef.current = new BrowserOAuthClientProvider(url, {
        storageKeyPrefix,
        clientName: clientConfig.name,
        clientUri: clientConfig.uri,
        logoUri: clientConfig.logo_uri || "https://mcp-use.com/logo.png",
        callbackUrl,
        preventAutoAuth,
        useRedirectFlow,
        onPopupWindow
      });
      addLog("debug", "BrowserOAuthClientProvider initialized in connect.");
    }
    if (!clientRef.current) {
      clientRef.current = new BrowserMCPClient();
      addLog("debug", "BrowserMCPClient initialized in connect.");
    }
    const tryConnectWithTransport = /* @__PURE__ */ __name(async (transportTypeParam, isAuthRetry = false) => {
      addLog(
        "info",
        `Attempting connection with transport: ${transportTypeParam}`
      );
      try {
        const serverName = "inspector-server";
        const serverConfig = {
          url: finalUrl,
          transport: transportTypeParam === "sse" ? "http" : transportTypeParam,
          // Disable SSE fallback when using explicit HTTP transport (not SSE)
          // This prevents automatic HTTP → SSE fallback at the connector level
          disableSseFallback: transportTypeParam === "http",
          // Use SSE transport when explicitly requested
          preferSse: transportTypeParam === "sse",
          clientInfo: {
            name: "mcp-use Inspector",
            version: getPackageVersion()
          }
        };
        if (allHeaders && Object.keys(allHeaders).length > 0) {
          serverConfig.headers = allHeaders;
        }
        if (authProviderRef.current) {
          const tokens = await authProviderRef.current.tokens();
          if (tokens?.access_token) {
            serverConfig.headers = {
              ...serverConfig.headers,
              Authorization: `Bearer ${tokens.access_token}`
            };
          }
        }
        clientRef.current.addServer(serverName, {
          ...serverConfig,
          authProvider: authProviderRef.current,
          // ← SDK handles OAuth automatically!
          clientOptions: clientConfig,
          // ← Pass client config to connector
          samplingCallback,
          // ← Pass sampling callback to connector
          elicitationCallback: onElicitation,
          // ← Pass elicitation callback to connector
          wrapTransport: wrapTransport ? (transport) => {
            console.log(
              "[useMcp] Applying transport wrapper for server:",
              serverName,
              "url:",
              url
            );
            return wrapTransport(transport, url);
          } : void 0
        });
        const session = await clientRef.current.createSession(
          serverName,
          false
        );
        session.on("notification", (notification) => {
          onNotification?.(notification);
          if (notification.method === "notifications/tools/list_changed") {
            addLog("info", "Tools list changed, auto-refreshing...");
            refreshTools().catch(
              (err) => addLog("warn", "Auto-refresh tools failed:", err)
            );
          } else if (notification.method === "notifications/resources/list_changed") {
            addLog("info", "Resources list changed, auto-refreshing...");
            refreshResources().catch(
              (err) => addLog("warn", "Auto-refresh resources failed:", err)
            );
          } else if (notification.method === "notifications/prompts/list_changed") {
            addLog("info", "Prompts list changed, auto-refreshing...");
            refreshPrompts().catch(
              (err) => addLog("warn", "Auto-refresh prompts failed:", err)
            );
          }
        });
        await session.initialize();
        addLog("info", "\u2705 Successfully connected to MCP server");
        addLog("info", "Server info:", session.connector.serverInfo);
        addLog(
          "info",
          "Server capabilities:",
          session.connector.serverCapabilities
        );
        console.log("[useMcp] Server info:", session.connector.serverInfo);
        console.log(
          "[useMcp] Server capabilities:",
          session.connector.serverCapabilities
        );
        setState("ready");
        successfulTransportRef.current = transportTypeParam;
        const setupConnectionMonitoring = /* @__PURE__ */ __name(() => {
          let healthCheckInterval = null;
          let lastSuccessfulCheck = Date.now();
          const HEALTH_CHECK_INTERVAL = 1e4;
          const HEALTH_CHECK_TIMEOUT = 3e4;
          const checkConnectionHealth = /* @__PURE__ */ __name(async () => {
            if (!isMountedRef.current || stateRef.current !== "ready") {
              if (healthCheckInterval) {
                clearInterval(healthCheckInterval);
                healthCheckInterval = null;
              }
              return;
            }
            try {
              await session.connector.listTools();
              lastSuccessfulCheck = Date.now();
            } catch (err) {
              const timeSinceLastSuccess = Date.now() - lastSuccessfulCheck;
              if (timeSinceLastSuccess > HEALTH_CHECK_TIMEOUT) {
                addLog(
                  "warn",
                  `Connection appears to be broken (no response for ${Math.round(timeSinceLastSuccess / 1e3)}s), attempting to reconnect...`
                );
                if (healthCheckInterval) {
                  clearInterval(healthCheckInterval);
                  healthCheckInterval = null;
                }
                if (autoReconnectRef.current && isMountedRef.current) {
                  setState("discovering");
                  addLog("info", "Auto-reconnecting to MCP server...");
                  setTimeout(
                    () => {
                      if (isMountedRef.current && stateRef.current === "discovering") {
                        connect();
                      }
                    },
                    typeof autoReconnectRef.current === "number" ? autoReconnectRef.current : DEFAULT_RECONNECT_DELAY
                  );
                }
              }
            }
          }, "checkConnectionHealth");
          healthCheckInterval = setInterval(
            checkConnectionHealth,
            HEALTH_CHECK_INTERVAL
          );
          return () => {
            if (healthCheckInterval) {
              clearInterval(healthCheckInterval);
              healthCheckInterval = null;
            }
          };
        }, "setupConnectionMonitoring");
        if (autoReconnect) {
          const cleanup = setupConnectionMonitoring();
          session._healthCheckCleanup = cleanup;
        }
        Tel.getInstance().trackUseMcpConnection({
          url,
          transportType: transportTypeParam,
          success: true,
          hasOAuth: !!authProviderRef.current,
          hasSampling: !!samplingCallback,
          hasElicitation: !!onElicitation
        }).catch(() => {
        });
        setTools(session.connector.tools || []);
        const resourcesResult = await session.connector.listAllResources();
        setResources(resourcesResult.resources || []);
        const promptsResult = await session.connector.listPrompts();
        setPrompts(promptsResult.prompts || []);
        const serverInfo2 = session.connector.serverInfo;
        const capabilities2 = session.connector.serverCapabilities;
        if (serverInfo2) {
          console.log("[useMcp] Server info:", serverInfo2);
          setServerInfo(serverInfo2);
          const loadIconPromise = (async () => {
            try {
              const serverIcons = serverInfo2.icons;
              if (serverIcons && Array.isArray(serverIcons) && serverIcons.length > 0) {
                const iconUrl = serverIcons[0].src || serverIcons[0].url;
                if (iconUrl) {
                  addLog("info", "Server provided icon:", iconUrl);
                  const res = await fetch(iconUrl);
                  const blob = await res.blob();
                  const base64 = await new Promise(
                    (resolve, reject) => {
                      const reader = new FileReader();
                      reader.onloadend = () => resolve(reader.result);
                      reader.onerror = reject;
                      reader.readAsDataURL(blob);
                    }
                  );
                  if (isMountedRef.current) {
                    setServerInfo(
                      (prev) => prev ? { ...prev, icon: base64 } : void 0
                    );
                    addLog("debug", "Server icon converted to base64");
                  }
                  return base64;
                }
              }
              if (url) {
                const faviconBase64 = await detectFavicon(url);
                if (faviconBase64 && isMountedRef.current) {
                  setServerInfo(
                    (prev) => prev ? { ...prev, icon: faviconBase64 } : void 0
                  );
                  addLog("debug", "Favicon detected and added to serverInfo");
                  return faviconBase64;
                }
              }
              return null;
            } catch (err) {
              addLog("debug", "Icon loading failed (non-critical):", err);
              return null;
            }
          })();
          iconLoadingPromiseRef.current = loadIconPromise;
        }
        if (capabilities2) {
          console.log("[useMcp] Server capabilities:", capabilities2);
          setCapabilities(capabilities2);
        }
        if (authProviderRef.current) {
          const tokens = await authProviderRef.current.tokens();
          if (tokens?.access_token) {
            const expiresAt = tokens.expires_in ? Date.now() + tokens.expires_in * 1e3 : void 0;
            setAuthTokens({
              access_token: tokens.access_token,
              token_type: tokens.token_type || "Bearer",
              expires_at: expiresAt,
              refresh_token: tokens.refresh_token,
              scope: tokens.scope
            });
          }
        }
        return "success";
      } catch (err) {
        const error2 = err;
        const errorMessage = error2?.message || String(err);
        if (error2.code === 401 || errorMessage.includes("401") || errorMessage.includes("Unauthorized")) {
          if (authProviderRef.current) {
            addLog(
              "info",
              "Authentication required. OAuth provider available."
            );
            try {
              const { auth: auth2 } = await import("@modelcontextprotocol/sdk/client/auth.js");
              const baseUrl = new URL(url).origin;
              auth2(authProviderRef.current, { serverUrl: baseUrl }).catch(
                () => {
                }
              );
              setTimeout(() => {
                if (isMountedRef.current) {
                  const manualUrl = authProviderRef.current?.getLastAttemptedAuthUrl();
                  if (manualUrl) {
                    setAuthUrl(manualUrl);
                    addLog(
                      "info",
                      "Manual authentication URL available:",
                      manualUrl
                    );
                  } else {
                    addLog("warn", "Could not generate authentication URL");
                  }
                }
              }, 100);
            } catch (authGenError) {
              addLog("warn", "Error generating auth URL:", authGenError);
            }
            if (isMountedRef.current) {
              setState("pending_auth");
            }
            connectingRef.current = false;
            return "auth_redirect";
          }
          if (customHeaders && Object.keys(customHeaders).length > 0) {
            failConnection(
              "Authentication failed: Server returned 401 Unauthorized. Check your Authorization header value is correct."
            );
            return "failed";
          }
          failConnection(
            "Authentication required: Server returned 401 Unauthorized. Add an Authorization header in the Custom Headers section (e.g., Authorization: Bearer YOUR_API_KEY)."
          );
          return "failed";
        }
        failConnection(
          errorMessage,
          error2 instanceof Error ? error2 : new Error(String(error2))
        );
        return "failed";
      }
    }, "tryConnectWithTransport");
    let finalStatus = "failed";
    if (transportType === "sse") {
      addLog("debug", "Using SSE-only transport mode");
      finalStatus = await tryConnectWithTransport("sse");
    } else if (transportType === "http") {
      addLog("debug", "Using HTTP-only transport mode");
      finalStatus = await tryConnectWithTransport("http");
    } else {
      addLog("debug", "Using auto transport mode (HTTP with SSE fallback)");
      const httpResult = await tryConnectWithTransport("http");
      if (httpResult === "fallback" && isMountedRef.current && stateRef.current !== "authenticating") {
        addLog("info", "HTTP failed, attempting SSE fallback...");
        const sseResult = await tryConnectWithTransport("sse");
        finalStatus = sseResult;
      } else {
        finalStatus = httpResult;
      }
    }
    if (finalStatus === "success" || finalStatus === "failed" || finalStatus === "auth_redirect") {
      connectingRef.current = false;
    }
    addLog("debug", `Connection sequence finished with status: ${finalStatus}`);
  }, [
    addLog,
    failConnection,
    disconnect,
    url,
    storageKeyPrefix,
    callbackUrl,
    clientConfig.name,
    clientConfig.version,
    clientConfig.uri,
    clientConfig.logo_uri,
    customHeaders,
    transportType,
    preventAutoAuth,
    useRedirectFlow,
    onPopupWindow,
    enabled,
    timeout,
    sseReadTimeout
  ]);
  (0, import_react.useEffect)(() => {
    connectRef.current = connect;
    failConnectionRef.current = failConnection;
  }, [connect, failConnection]);
  const callTool = (0, import_react.useCallback)(
    async (name, args, options2) => {
      if (stateRef.current !== "ready" || !clientRef.current) {
        throw new Error(
          `MCP client is not ready (current state: ${state}). Cannot call tool "${name}".`
        );
      }
      addLog("info", `Calling tool: ${name}`, args);
      const startTime = Date.now();
      try {
        const serverName = "inspector-server";
        const session = clientRef.current.getSession(serverName);
        if (!session) {
          throw new Error("No active session found");
        }
        const result = await session.connector.callTool(
          name,
          args || {},
          options2
        );
        addLog("info", `Tool "${name}" call successful:`, result);
        Tel.getInstance().trackUseMcpToolCall({
          toolName: name,
          success: true,
          executionTimeMs: Date.now() - startTime
        }).catch(() => {
        });
        return result;
      } catch (err) {
        addLog("error", `Tool "${name}" call failed:`, err);
        Tel.getInstance().trackUseMcpToolCall({
          toolName: name,
          success: false,
          errorType: err instanceof Error ? err.name : "UnknownError",
          executionTimeMs: Date.now() - startTime
        }).catch(() => {
        });
        throw err;
      }
    },
    [state]
  );
  const retry = (0, import_react.useCallback)(() => {
    if (stateRef.current === "failed") {
      addLog("info", "Retry requested...");
      connectRef.current?.();
    } else {
      addLog(
        "warn",
        `Retry called but state is not 'failed' (state: ${stateRef.current}). Ignoring.`
      );
    }
  }, [addLog]);
  const authenticate = (0, import_react.useCallback)(async () => {
    addLog("info", "Manual authentication requested...");
    const currentState = stateRef.current;
    if (currentState === "failed") {
      addLog("info", "Attempting to reconnect and authenticate via retry...");
      retry();
    } else if (currentState === "pending_auth") {
      addLog("info", "Proceeding with authentication from pending state...");
      try {
        assert(
          authProviderRef.current,
          "Auth Provider not available for manual auth"
        );
        assert(url, "Server URL is required for authentication");
        addLog("info", "Clearing all OAuth state and initiating fresh flow...");
        const hashPrefix = `${storageKeyPrefix}:${authProviderRef.current.serverUrlHash}`;
        Object.keys(localStorage).forEach((key) => {
          if (key.startsWith(hashPrefix)) {
            addLog("debug", `Removing stale OAuth key: ${key}`);
            localStorage.removeItem(key);
          }
          if (key.startsWith(`${storageKeyPrefix}:state_`)) {
            addLog("debug", `Removing orphaned state: ${key}`);
            localStorage.removeItem(key);
          }
        });
        setState("authenticating");
        const freshAuthProvider = new BrowserOAuthClientProvider(url, {
          storageKeyPrefix,
          clientName: clientConfig.name,
          clientUri: clientConfig.uri,
          logoUri: clientConfig.logo_uri || "https://mcp-use.com/logo.png",
          callbackUrl,
          preventAutoAuth: false,
          // ← Allow OAuth to proceed
          useRedirectFlow,
          onPopupWindow
        });
        authProviderRef.current = freshAuthProvider;
        addLog("info", "Triggering fresh OAuth authorization...");
        const { auth: auth2 } = await import("@modelcontextprotocol/sdk/client/auth.js");
        const baseUrl = new URL(url).origin;
        auth2(freshAuthProvider, {
          serverUrl: baseUrl
        }).catch((err) => {
          addLog(
            "info",
            "OAuth flow initiated:",
            err instanceof Error ? err.message : "Redirecting..."
          );
        });
      } catch (authError) {
        if (!isMountedRef.current) return;
        setState("pending_auth");
        addLog(
          "error",
          `Manual authentication failed: ${authError instanceof Error ? authError.message : String(authError)}`
        );
      }
    } else if (currentState === "authenticating") {
      addLog(
        "warn",
        "Already attempting authentication. Check for blocked popups or wait for timeout."
      );
      const manualUrl = authProviderRef.current?.getLastAttemptedAuthUrl();
      if (manualUrl && !authUrl) {
        setAuthUrl(manualUrl);
        addLog("info", "Manual authentication URL retrieved:", manualUrl);
      }
    } else {
      addLog(
        "info",
        `Client not in a state requiring manual authentication trigger (state: ${currentState}). If needed, try disconnecting and reconnecting.`
      );
    }
  }, [
    addLog,
    retry,
    authUrl,
    url,
    useRedirectFlow,
    onPopupWindow,
    storageKeyPrefix,
    clientConfig.name,
    clientConfig.uri,
    clientConfig.logo_uri,
    callbackUrl
  ]);
  const clearStorage = (0, import_react.useCallback)(() => {
    if (authProviderRef.current) {
      const count = authProviderRef.current.clearStorage();
      addLog("info", `Cleared ${count} item(s) from localStorage for ${url}.`);
      setAuthUrl(void 0);
      disconnect();
    } else {
      addLog("warn", "Auth provider not initialized, cannot clear storage.");
    }
  }, [url, addLog, disconnect]);
  const listResources = (0, import_react.useCallback)(async () => {
    if (stateRef.current !== "ready" || !clientRef.current) {
      throw new Error(
        `MCP client is not ready (current state: ${state}). Cannot list resources.`
      );
    }
    addLog("info", "Listing resources");
    try {
      const serverName = "inspector-server";
      const session = clientRef.current.getSession(serverName);
      if (!session) {
        throw new Error("No active session found");
      }
      const resourcesResult = await session.connector.listAllResources();
      setResources(resourcesResult.resources || []);
      addLog("info", "Resources listed successfully");
    } catch (err) {
      addLog("error", "List resources failed:", err);
      throw err;
    }
  }, [state]);
  const readResource = (0, import_react.useCallback)(
    async (uri) => {
      if (stateRef.current !== "ready" || !clientRef.current) {
        throw new Error(
          `MCP client is not ready (current state: ${state}). Cannot read resource.`
        );
      }
      addLog("info", `Reading resource: ${uri}`);
      try {
        const serverName = "inspector-server";
        const session = clientRef.current.getSession(serverName);
        if (!session) {
          throw new Error("No active session found");
        }
        const result = await session.connector.readResource(uri);
        addLog("info", "Resource read successful:", result);
        Tel.getInstance().trackUseMcpResourceRead({
          resourceUri: uri,
          success: true
        }).catch(() => {
        });
        return result;
      } catch (err) {
        addLog("error", "Resource read failed:", err);
        Tel.getInstance().trackUseMcpResourceRead({
          resourceUri: uri,
          success: false,
          errorType: err instanceof Error ? err.name : "UnknownError"
        }).catch(() => {
        });
        throw err;
      }
    },
    [state]
  );
  const listPrompts = (0, import_react.useCallback)(async () => {
    if (stateRef.current !== "ready" || !clientRef.current) {
      throw new Error(
        `MCP client is not ready (current state: ${state}). Cannot list prompts.`
      );
    }
    addLog("info", "Listing prompts");
    try {
      const serverName = "inspector-server";
      const session = clientRef.current.getSession(serverName);
      if (!session) {
        throw new Error("No active session found");
      }
      const promptsResult = await session.connector.listPrompts();
      setPrompts(promptsResult.prompts || []);
      addLog("info", "Prompts listed successfully");
    } catch (err) {
      addLog("error", "List prompts failed:", err);
      throw err;
    }
  }, [state]);
  const refreshTools = (0, import_react.useCallback)(async () => {
    if (stateRef.current !== "ready" || !clientRef.current) {
      addLog("debug", "Cannot refresh tools - client not ready");
      return;
    }
    addLog("debug", "Refreshing tools list");
    try {
      const serverName = "inspector-server";
      const session = clientRef.current.getSession(serverName);
      if (!session) {
        addLog("warn", "No active session found for tools refresh");
        return;
      }
      const toolsResult = await session.connector.listTools();
      setTools(toolsResult || []);
      addLog("info", "Tools list refreshed successfully");
    } catch (err) {
      addLog("warn", "Failed to refresh tools:", err);
    }
  }, [addLog]);
  const refreshResources = (0, import_react.useCallback)(async () => {
    if (stateRef.current !== "ready" || !clientRef.current) {
      addLog("debug", "Cannot refresh resources - client not ready");
      return;
    }
    addLog("debug", "Refreshing resources list");
    try {
      const serverName = "inspector-server";
      const session = clientRef.current.getSession(serverName);
      if (!session) {
        addLog("warn", "No active session found for resources refresh");
        return;
      }
      const resourcesResult = await session.connector.listAllResources();
      setResources(resourcesResult.resources || []);
      addLog("info", "Resources list refreshed successfully");
    } catch (err) {
      addLog("warn", "Failed to refresh resources:", err);
    }
  }, [addLog]);
  const refreshPrompts = (0, import_react.useCallback)(async () => {
    if (stateRef.current !== "ready" || !clientRef.current) {
      addLog("debug", "Cannot refresh prompts - client not ready");
      return;
    }
    addLog("debug", "Refreshing prompts list");
    try {
      const serverName = "inspector-server";
      const session = clientRef.current.getSession(serverName);
      if (!session) {
        addLog("warn", "No active session found for prompts refresh");
        return;
      }
      const promptsResult = await session.connector.listPrompts();
      setPrompts(promptsResult.prompts || []);
      addLog("info", "Prompts list refreshed successfully");
    } catch (err) {
      addLog("warn", "Failed to refresh prompts:", err);
    }
  }, [addLog]);
  const refreshAll = (0, import_react.useCallback)(async () => {
    addLog("info", "Refreshing all lists (tools, resources, prompts)");
    await Promise.all([refreshTools(), refreshResources(), refreshPrompts()]);
  }, [refreshTools, refreshResources, refreshPrompts, addLog]);
  const getPrompt = (0, import_react.useCallback)(
    async (name, args) => {
      if (stateRef.current !== "ready" || !clientRef.current) {
        throw new Error(
          `MCP client is not ready (current state: ${state}). Cannot get prompt.`
        );
      }
      addLog("info", `Getting prompt: ${name}`, args);
      try {
        const serverName = "inspector-server";
        const session = clientRef.current.getSession(serverName);
        if (!session) {
          throw new Error("No active session found");
        }
        const result = await session.connector.getPrompt(name, args || {});
        addLog("info", `Prompt "${name}" retrieved successfully:`, result);
        return result;
      } catch (err) {
        addLog("error", `Prompt "${name}" retrieval failed:`, err);
        throw err;
      }
    },
    [state]
  );
  (0, import_react.useEffect)(() => {
    const messageHandler = /* @__PURE__ */ __name((event) => {
      if (event.origin !== window.location.origin) return;
      if (event.data?.type === "mcp_auth_callback") {
        addLog("info", "Received auth callback message.", event.data);
        if (authTimeoutRef.current) clearTimeout(authTimeoutRef.current);
        authTimeoutRef.current = null;
        if (event.data.success) {
          addLog(
            "info",
            "Authentication successful via popup. Reconnecting client..."
          );
          if (connectingRef.current) {
            addLog(
              "debug",
              "Connection attempt already in progress, resetting flag to allow reconnection."
            );
          }
          connectingRef.current = false;
          setTimeout(() => {
            if (isMountedRef.current) {
              addLog(
                "debug",
                "Initiating reconnection after successful auth callback."
              );
              connectRef.current?.();
            }
          }, 100);
        } else {
          failConnectionRef.current?.(
            `Authentication failed in callback: ${event.data.error || "Unknown reason."}`
          );
        }
      }
    }, "messageHandler");
    window.addEventListener("message", messageHandler);
    addLog("debug", "Auth callback message listener added.");
    return () => {
      window.removeEventListener("message", messageHandler);
      addLog("debug", "Auth callback message listener removed.");
      if (authTimeoutRef.current) clearTimeout(authTimeoutRef.current);
    };
  }, [addLog]);
  (0, import_react.useEffect)(() => {
    isMountedRef.current = true;
    if (!enabled || !url) {
      addLog(
        "debug",
        enabled ? "No server URL provided, skipping connection." : "Connection disabled via enabled flag."
      );
      setState("discovering");
      return () => {
        isMountedRef.current = false;
      };
    }
    addLog("debug", "useMcp mounted, initiating connection.");
    connectAttemptRef.current = 0;
    if (!authProviderRef.current || authProviderRef.current.serverUrl !== url) {
      authProviderRef.current = new BrowserOAuthClientProvider(url, {
        storageKeyPrefix,
        clientName: clientConfig.name,
        clientUri: clientConfig.uri,
        logoUri: clientConfig.logo_uri || "https://mcp-use.com/logo.png",
        callbackUrl,
        preventAutoAuth,
        useRedirectFlow,
        onPopupWindow
      });
      addLog(
        "debug",
        "BrowserOAuthClientProvider initialized/updated on mount/option change."
      );
    }
    connect();
    return () => {
      isMountedRef.current = false;
      addLog("debug", "useMcp unmounting, disconnecting.");
      disconnect(true);
    };
  }, [
    url,
    enabled,
    storageKeyPrefix,
    callbackUrl,
    clientConfig.name,
    clientConfig.version,
    clientConfig.uri,
    clientConfig.logo_uri,
    useRedirectFlow
  ]);
  const retryRef = (0, import_react.useRef)(retry);
  const addLogRef = (0, import_react.useRef)(addLog);
  (0, import_react.useEffect)(() => {
    retryRef.current = retry;
    addLogRef.current = addLog;
  }, [retry, addLog]);
  (0, import_react.useEffect)(() => {
    let retryTimeoutId = null;
    if (state === "failed" && autoRetry && connectAttemptRef.current > 0) {
      if (!retryScheduledRef.current) {
        retryScheduledRef.current = true;
        const delay = typeof autoRetry === "number" ? autoRetry : DEFAULT_RETRY_DELAY;
        addLogRef.current(
          "info",
          `Connection failed, auto-retrying in ${delay}ms...`
        );
        retryTimeoutId = setTimeout(() => {
          retryScheduledRef.current = false;
          if (isMountedRef.current && stateRef.current === "failed") {
            retryRef.current();
          }
        }, delay);
      }
    } else if (state !== "failed") {
      retryScheduledRef.current = false;
    }
    return () => {
      if (retryTimeoutId) {
        clearTimeout(retryTimeoutId);
        retryScheduledRef.current = false;
      }
    };
  }, [state, autoRetry]);
  const ensureIconLoaded = (0, import_react.useCallback)(async () => {
    if (stateRef.current !== "ready") {
      addLog("warn", "Cannot ensure icon loaded - not connected");
      return null;
    }
    if (serverInfo?.icon) {
      return serverInfo.icon;
    }
    if (iconLoadingPromiseRef.current) {
      addLog("debug", "Waiting for icon to finish loading...");
      const icon = await iconLoadingPromiseRef.current;
      return icon;
    }
    addLog("debug", "No icon available and no loading in progress");
    return null;
  }, [serverInfo, addLog]);
  return {
    state,
    name: serverInfo?.name || url || "",
    tools,
    resources,
    resourceTemplates,
    prompts,
    serverInfo,
    capabilities,
    error,
    log,
    authUrl,
    authTokens,
    client: clientRef.current,
    callTool,
    readResource,
    listResources,
    listPrompts,
    getPrompt,
    refreshTools,
    refreshResources,
    refreshPrompts,
    refreshAll,
    retry,
    disconnect,
    authenticate,
    clearStorage,
    ensureIconLoaded
  };
}
__name(useMcp, "useMcp");

// src/react/index.ts
init_telemetry_browser();
init_telemetry_browser();
init_telemetry_browser();

// src/react/ErrorBoundary.tsx
var import_react2 = __toESM(require("react"), 1);
var ErrorBoundary = class extends import_react2.default.Component {
  static {
    __name(this, "ErrorBoundary");
  }
  constructor(props) {
    super(props);
    this.state = { hasError: false, error: null };
  }
  static getDerivedStateFromError(error) {
    return { hasError: true, error };
  }
  componentDidCatch(error, errorInfo) {
    console.error("Widget Error:", error, errorInfo);
  }
  render() {
    if (this.state.hasError) {
      return /* @__PURE__ */ import_react2.default.createElement("div", { className: "p-4 border border-red-500 bg-red-50 text-red-900 rounded-md dark:bg-red-900/20 dark:text-red-100" }, /* @__PURE__ */ import_react2.default.createElement("h3", { className: "font-bold mb-2" }, "Widget Error"), /* @__PURE__ */ import_react2.default.createElement("pre", { className: "text-sm whitespace-pre-wrap" }, this.state.error?.message));
    }
    return this.props.children;
  }
};

// src/react/Image.tsx
var import_react3 = __toESM(require("react"), 1);
var Image = /* @__PURE__ */ __name(({ src, ...props }) => {
  const publicUrl = typeof window !== "undefined" ? window.__mcpPublicAssetsUrl || window.__mcpPublicUrl || "" : "";
  const getFinalSrc = /* @__PURE__ */ __name((source) => {
    if (!source) return source;
    if (source.startsWith("http://") || source.startsWith("https://") || source.startsWith("data:")) {
      return source;
    }
    if (!publicUrl) {
      return source;
    }
    const cleanSrc = source.startsWith("/") ? source.slice(1) : source;
    return `${publicUrl}/${cleanSrc}`;
  }, "getFinalSrc");
  const finalSrc = getFinalSrc(src);
  return /* @__PURE__ */ import_react3.default.createElement("img", { src: finalSrc, ...props });
}, "Image");

// src/react/ThemeProvider.tsx
var import_react5 = __toESM(require("react"), 1);

// src/react/useWidget.ts
var import_react4 = require("react");

// src/react/widget-types.ts
var SET_GLOBALS_EVENT_TYPE = "openai:set_globals";

// src/react/useWidget.ts
function useOpenAiGlobal(key) {
  return (0, import_react4.useSyncExternalStore)(
    (onChange) => {
      const handleSetGlobal = /* @__PURE__ */ __name((event) => {
        const customEvent = event;
        const value = customEvent.detail.globals[key];
        if (value === void 0) {
          return;
        }
        onChange();
      }, "handleSetGlobal");
      if (typeof window !== "undefined") {
        window.addEventListener(SET_GLOBALS_EVENT_TYPE, handleSetGlobal);
      }
      return () => {
        if (typeof window !== "undefined") {
          window.removeEventListener(SET_GLOBALS_EVENT_TYPE, handleSetGlobal);
        }
      };
    },
    () => typeof window !== "undefined" && window.openai ? window.openai[key] : void 0
  );
}
__name(useOpenAiGlobal, "useOpenAiGlobal");
function useWidget(defaultProps) {
  const [isOpenAiAvailable, setIsOpenAiAvailable] = (0, import_react4.useState)(
    () => typeof window !== "undefined" && !!window.openai
  );
  (0, import_react4.useEffect)(() => {
    if (typeof window !== "undefined" && window.openai) {
      setIsOpenAiAvailable(true);
      return;
    }
    const checkInterval = setInterval(() => {
      if (typeof window !== "undefined" && window.openai) {
        setIsOpenAiAvailable(true);
        clearInterval(checkInterval);
      }
    }, 100);
    const handleSetGlobals = /* @__PURE__ */ __name(() => {
      if (typeof window !== "undefined" && window.openai) {
        setIsOpenAiAvailable(true);
        clearInterval(checkInterval);
      }
    }, "handleSetGlobals");
    if (typeof window !== "undefined") {
      window.addEventListener(SET_GLOBALS_EVENT_TYPE, handleSetGlobals);
    }
    const timeout = setTimeout(() => {
      clearInterval(checkInterval);
      if (typeof window !== "undefined") {
        window.removeEventListener(SET_GLOBALS_EVENT_TYPE, handleSetGlobals);
      }
    }, 5e3);
    return () => {
      clearInterval(checkInterval);
      clearTimeout(timeout);
      if (typeof window !== "undefined") {
        window.removeEventListener(SET_GLOBALS_EVENT_TYPE, handleSetGlobals);
      }
    };
  }, []);
  const provider = (0, import_react4.useMemo)(() => {
    return isOpenAiAvailable ? "openai" : "mcp-ui";
  }, [isOpenAiAvailable]);
  const searchString = typeof window !== "undefined" ? window.location.search : "";
  const urlParams = (0, import_react4.useMemo)(() => {
    const urlParams2 = new URLSearchParams(searchString);
    if (urlParams2.has("mcpUseParams")) {
      return JSON.parse(urlParams2.get("mcpUseParams"));
    }
    return {
      toolInput: {},
      toolOutput: {},
      toolId: ""
    };
  }, [searchString]);
  const toolInput = provider === "openai" ? useOpenAiGlobal("toolInput") : urlParams.toolInput;
  const toolOutput = provider === "openai" ? useOpenAiGlobal("toolOutput") : urlParams.toolOutput;
  const toolResponseMetadata = useOpenAiGlobal("toolResponseMetadata");
  const widgetProps = (0, import_react4.useMemo)(() => {
    if (toolResponseMetadata && typeof toolResponseMetadata === "object") {
      const metaProps = toolResponseMetadata["mcp-use/props"];
      if (metaProps) {
        return metaProps;
      }
    }
    return defaultProps || {};
  }, [toolResponseMetadata, defaultProps]);
  const widgetState = useOpenAiGlobal("widgetState");
  const theme = useOpenAiGlobal("theme");
  const displayMode = useOpenAiGlobal("displayMode");
  const safeArea = useOpenAiGlobal("safeArea");
  const maxHeight = useOpenAiGlobal("maxHeight");
  const userAgent = useOpenAiGlobal("userAgent");
  const locale = useOpenAiGlobal("locale");
  const mcp_url = (0, import_react4.useMemo)(() => {
    if (typeof window !== "undefined" && window.__mcpPublicUrl) {
      return window.__mcpPublicUrl.replace(/\/mcp-use\/public$/, "");
    }
    return "";
  }, []);
  const [localWidgetState, setLocalWidgetState] = (0, import_react4.useState)(null);
  (0, import_react4.useEffect)(() => {
    if (widgetState !== void 0) {
      setLocalWidgetState(widgetState);
    }
  }, [widgetState]);
  const callTool = (0, import_react4.useCallback)(
    async (name, args) => {
      if (!window.openai?.callTool) {
        throw new Error("window.openai.callTool is not available");
      }
      return window.openai.callTool(name, args);
    },
    []
  );
  const sendFollowUpMessage = (0, import_react4.useCallback)(
    async (prompt) => {
      if (!window.openai?.sendFollowUpMessage) {
        throw new Error("window.openai.sendFollowUpMessage is not available");
      }
      return window.openai.sendFollowUpMessage({ prompt });
    },
    []
  );
  const openExternal = (0, import_react4.useCallback)((href) => {
    if (!window.openai?.openExternal) {
      throw new Error("window.openai.openExternal is not available");
    }
    window.openai.openExternal({ href });
  }, []);
  const requestDisplayMode = (0, import_react4.useCallback)(
    async (mode) => {
      if (!window.openai?.requestDisplayMode) {
        throw new Error("window.openai.requestDisplayMode is not available");
      }
      return window.openai.requestDisplayMode({ mode });
    },
    []
  );
  const setState = (0, import_react4.useCallback)(
    async (state) => {
      if (!window.openai?.setWidgetState) {
        throw new Error("window.openai.setWidgetState is not available");
      }
      const currentState = widgetState !== void 0 ? widgetState : localWidgetState;
      const newState = typeof state === "function" ? state(currentState) : state;
      setLocalWidgetState(newState);
      return window.openai.setWidgetState(newState);
    },
    [widgetState, localWidgetState]
  );
  const isPending = (0, import_react4.useMemo)(() => {
    return provider === "openai" && toolResponseMetadata === null;
  }, [provider, toolResponseMetadata]);
  return {
    // Props and state (with defaults)
    props: widgetProps,
    toolInput: toolInput || {},
    output: toolOutput ?? null,
    metadata: toolResponseMetadata ?? null,
    state: localWidgetState,
    setState,
    // Layout and theme (with safe defaults)
    theme: theme || "light",
    displayMode: displayMode || "inline",
    safeArea: safeArea || { insets: { top: 0, bottom: 0, left: 0, right: 0 } },
    maxHeight: maxHeight || 600,
    userAgent: userAgent || {
      device: { type: "desktop" },
      capabilities: { hover: true, touch: false }
    },
    locale: locale || "en",
    mcp_url,
    // Actions
    callTool,
    sendFollowUpMessage,
    openExternal,
    requestDisplayMode,
    // Availability
    isAvailable: isOpenAiAvailable,
    isPending
  };
}
__name(useWidget, "useWidget");
function useWidgetProps(defaultProps) {
  const { props } = useWidget(defaultProps);
  return props;
}
__name(useWidgetProps, "useWidgetProps");
function useWidgetTheme() {
  const { theme } = useWidget();
  return theme;
}
__name(useWidgetTheme, "useWidgetTheme");
function useWidgetState(defaultState) {
  const { state, setState } = useWidget();
  (0, import_react4.useEffect)(() => {
    if (state === null && defaultState !== void 0 && window.openai?.setWidgetState) {
      setState(defaultState);
    }
  }, []);
  return [state, setState];
}
__name(useWidgetState, "useWidgetState");

// src/react/ThemeProvider.tsx
var ThemeProvider = /* @__PURE__ */ __name(({
  children
}) => {
  const { theme, isAvailable } = useWidget();
  console.log("theme", theme);
  const [systemPreference, setSystemPreference] = (0, import_react5.useState)(
    () => {
      if (typeof window === "undefined") return "light";
      return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
    }
  );
  (0, import_react5.useEffect)(() => {
    if (typeof window === "undefined") return;
    const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
    const handleChange = /* @__PURE__ */ __name((e) => {
      setSystemPreference(e.matches ? "dark" : "light");
    }, "handleChange");
    mediaQuery.addEventListener("change", handleChange);
    return () => mediaQuery.removeEventListener("change", handleChange);
  }, []);
  const effectiveTheme = isAvailable ? theme : systemPreference;
  (0, import_react5.useLayoutEffect)(() => {
    if (typeof document === "undefined") return;
    if (effectiveTheme === "dark") {
      document.documentElement.classList.add("dark");
    } else {
      document.documentElement.classList.remove("dark");
    }
  }, [effectiveTheme]);
  return /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, children);
}, "ThemeProvider");

// src/react/WidgetControls.tsx
var import_react6 = __toESM(require("react"), 1);
function WidgetControls({
  children,
  className = "",
  position = "top-right",
  attachTo,
  showLabels = true,
  debugger: enableDebugger = false,
  viewControls = false
}) {
  const {
    props,
    output,
    metadata,
    state,
    theme,
    displayMode,
    safeArea,
    maxHeight,
    userAgent,
    locale,
    isAvailable,
    callTool,
    sendFollowUpMessage,
    openExternal,
    requestDisplayMode,
    setState
  } = useWidget();
  const [isHovered, setIsHovered] = (0, import_react6.useState)(false);
  const [isOverlayOpen, setIsOverlayOpen] = (0, import_react6.useState)(false);
  const containerRef = (0, import_react6.useRef)(null);
  const overlayRef = (0, import_react6.useRef)(null);
  const [windowOpenAiKeys, setWindowOpenAiKeys] = (0, import_react6.useState)([]);
  const [actionResult, setActionResult] = (0, import_react6.useState)("");
  const [toolName, setToolName] = (0, import_react6.useState)("get-my-city");
  const [toolArgs, setToolArgs] = (0, import_react6.useState)("{}");
  const [followUpMessage, setFollowUpMessage] = (0, import_react6.useState)(
    "Test follow-up message"
  );
  const [externalUrl, setExternalUrl] = (0, import_react6.useState)(
    "https://docs.mcp-use.com"
  );
  const isFullscreen = displayMode === "fullscreen" && isAvailable;
  const isPip = displayMode === "pip" && isAvailable;
  const isInInspector = typeof window !== "undefined" && window.location.pathname.includes("/inspector/api/");
  (0, import_react6.useEffect)(() => {
    const timeoutId = setTimeout(() => {
      if (typeof window !== "undefined" && window.openai) {
        try {
          const keys = Object.keys(window.openai);
          setWindowOpenAiKeys(keys);
        } catch (e) {
          setWindowOpenAiKeys([]);
        }
      } else {
        setWindowOpenAiKeys([]);
      }
    }, 100);
    return () => {
      clearTimeout(timeoutId);
    };
  }, []);
  const isDark = theme === "dark";
  const getPositionClasses = /* @__PURE__ */ __name(() => {
    const baseClasses = [
      "absolute",
      "z-[1000]",
      "flex",
      "gap-2",
      "transition-opacity",
      "duration-200",
      "ease-in-out",
      isHovered ? "opacity-100" : "opacity-0",
      isHovered ? "pointer-events-auto" : "pointer-events-none"
    ];
    switch (position) {
      case "top-left":
        return [...baseClasses, "top-4", "left-4"];
      case "top-center":
        return [...baseClasses, "top-4", "left-1/2", "-translate-x-1/2"];
      case "top-right":
        return [...baseClasses, "top-4", "right-4"];
      case "center-left":
        return [...baseClasses, "top-1/2", "left-4", "-translate-y-1/2"];
      case "center-right":
        return [...baseClasses, "top-1/2", "right-4", "-translate-y-1/2"];
      case "bottom-left":
        return [...baseClasses, "bottom-4", "left-4"];
      case "bottom-center":
        return [...baseClasses, "bottom-4", "left-1/2", "-translate-x-1/2"];
      case "bottom-right":
        return [...baseClasses, "bottom-4", "right-4"];
      default:
        return [...baseClasses, "top-4", "right-4"];
    }
  }, "getPositionClasses");
  const getPositionOffsetStyles = /* @__PURE__ */ __name(() => {
    const baseOffset = 16;
    const topOffset = safeArea?.insets?.top ? Math.max(baseOffset, safeArea.insets.top + 8) : baseOffset;
    const rightOffset = safeArea?.insets?.right ? Math.max(baseOffset, safeArea.insets.right + 8) : baseOffset;
    const bottomOffset = safeArea?.insets?.bottom ? Math.max(baseOffset, safeArea.insets.bottom + 8) : baseOffset;
    const leftOffset = safeArea?.insets?.left ? Math.max(baseOffset, safeArea.insets.left + 8) : baseOffset;
    const styles = {};
    switch (position) {
      case "top-left":
        styles.top = `${topOffset}px`;
        styles.left = `${leftOffset}px`;
        break;
      case "top-center":
        styles.top = `${topOffset}px`;
        break;
      case "top-right":
        styles.top = `${topOffset}px`;
        styles.right = `${rightOffset}px`;
        break;
      case "center-left":
        styles.left = `${leftOffset}px`;
        break;
      case "center-right":
        styles.right = `${rightOffset}px`;
        break;
      case "bottom-left":
        styles.bottom = `${bottomOffset}px`;
        styles.left = `${leftOffset}px`;
        break;
      case "bottom-center":
        styles.bottom = `${bottomOffset}px`;
        break;
      case "bottom-right":
        styles.bottom = `${bottomOffset}px`;
        styles.right = `${rightOffset}px`;
        break;
      default:
        styles.top = `${topOffset}px`;
        styles.right = `${rightOffset}px`;
        break;
    }
    return styles;
  }, "getPositionOffsetStyles");
  (0, import_react6.useEffect)(() => {
    if (!attachTo) return;
    const handleMouseEnter = /* @__PURE__ */ __name(() => setIsHovered(true), "handleMouseEnter");
    const handleMouseLeave = /* @__PURE__ */ __name(() => setIsHovered(false), "handleMouseLeave");
    attachTo.addEventListener("mouseenter", handleMouseEnter);
    attachTo.addEventListener("mouseleave", handleMouseLeave);
    return () => {
      attachTo.removeEventListener("mouseenter", handleMouseEnter);
      attachTo.removeEventListener("mouseleave", handleMouseLeave);
    };
  }, [attachTo]);
  (0, import_react6.useEffect)(() => {
    if (!isOverlayOpen) return;
    const handleClickOutside = /* @__PURE__ */ __name((event) => {
      if (overlayRef.current && !overlayRef.current.contains(event.target)) {
        setIsOverlayOpen(false);
      }
    }, "handleClickOutside");
    document.addEventListener("mousedown", handleClickOutside);
    return () => {
      document.removeEventListener("mousedown", handleClickOutside);
    };
  }, [isOverlayOpen]);
  (0, import_react6.useEffect)(() => {
    if (isOverlayOpen) {
      document.body.style.overflow = "hidden";
    } else {
      document.body.style.overflow = "";
    }
    return () => {
      document.body.style.overflow = "";
    };
  }, [isOverlayOpen]);
  const handleToggleOverlay = /* @__PURE__ */ __name(() => {
    setIsOverlayOpen(!isOverlayOpen);
  }, "handleToggleOverlay");
  const handleCallTool = /* @__PURE__ */ __name(async () => {
    try {
      setActionResult("Calling tool...");
      const args = toolArgs.trim() ? JSON.parse(toolArgs) : {};
      const result = await callTool(toolName, args);
      setActionResult(`Success: ${JSON.stringify(result, null, 2)}`);
    } catch (error) {
      const err = error;
      setActionResult(`Error: ${err.message}`);
    }
  }, "handleCallTool");
  const handleSendFollowUpMessage = /* @__PURE__ */ __name(async () => {
    try {
      setActionResult("Sending follow-up message...");
      await sendFollowUpMessage(followUpMessage);
      setActionResult("Follow-up message sent successfully");
    } catch (error) {
      const err = error;
      setActionResult(`Error: ${err.message}`);
    }
  }, "handleSendFollowUpMessage");
  const handleOpenExternal = /* @__PURE__ */ __name(() => {
    try {
      openExternal(externalUrl);
      setActionResult(`Opened external link: ${externalUrl}`);
    } catch (error) {
      const err = error;
      setActionResult(`Error: ${err.message}`);
    }
  }, "handleOpenExternal");
  const handleRequestDisplayMode = /* @__PURE__ */ __name(async (mode) => {
    try {
      setActionResult(`Requesting display mode: ${mode}...`);
      const result = await requestDisplayMode(mode);
      setActionResult(`Display mode granted: ${result.mode}`);
    } catch (error) {
      const err = error;
      setActionResult(`Error: ${err.message}`);
    }
  }, "handleRequestDisplayMode");
  const handleSetState = /* @__PURE__ */ __name(async () => {
    try {
      const newState = state ? { ...state, debugTimestamp: (/* @__PURE__ */ new Date()).toISOString() } : { debugTimestamp: (/* @__PURE__ */ new Date()).toISOString() };
      setActionResult("Setting state...");
      await setState(newState);
      setActionResult(`State updated: ${JSON.stringify(newState, null, 2)}`);
    } catch (error) {
      const err = error;
      setActionResult(`Error: ${err.message}`);
    }
  }, "handleSetState");
  const handleFullscreen = /* @__PURE__ */ __name(async () => {
    try {
      await requestDisplayMode("fullscreen");
    } catch (error) {
      console.error("Failed to go fullscreen:", error);
    }
  }, "handleFullscreen");
  const handlePip = /* @__PURE__ */ __name(async () => {
    try {
      await requestDisplayMode("pip");
    } catch (error) {
      console.error("Failed to go pip:", error);
    }
  }, "handlePip");
  const getTooltipClasses = /* @__PURE__ */ __name(() => {
    const baseClasses = [
      "absolute",
      "px-2",
      "py-1",
      "bg-black/90",
      "text-white",
      "rounded",
      "text-xs",
      "whitespace-nowrap",
      "pointer-events-none",
      "transition-opacity",
      "duration-200",
      "ease-in-out"
    ];
    switch (position) {
      case "top-right":
        return [...baseClasses, "top-full", "right-0", "mt-2"];
      case "top-left":
        return [...baseClasses, "top-full", "left-0", "mt-2"];
      case "top-center":
        return [
          ...baseClasses,
          "top-full",
          "left-1/2",
          "-translate-x-1/2",
          "mt-2"
        ];
      case "bottom-right":
        return [...baseClasses, "bottom-full", "right-0", "mb-2"];
      case "bottom-left":
        return [...baseClasses, "bottom-full", "left-0", "mb-2"];
      case "bottom-center":
        return [
          ...baseClasses,
          "bottom-full",
          "left-1/2",
          "-translate-x-1/2",
          "mb-2"
        ];
      case "center-left":
        return [
          ...baseClasses,
          "left-full",
          "top-1/2",
          "-translate-y-1/2",
          "ml-2"
        ];
      case "center-right":
        return [
          ...baseClasses,
          "right-full",
          "top-1/2",
          "-translate-y-1/2",
          "mr-2"
        ];
      default:
        return [...baseClasses, "top-full", "right-0", "mt-2"];
    }
  }, "getTooltipClasses");
  const IconButton = /* @__PURE__ */ __name(({
    onClick,
    label,
    children: icon
  }) => {
    const [isButtonHovered, setIsButtonHovered] = (0, import_react6.useState)(false);
    const tooltipClasses = getTooltipClasses();
    return /* @__PURE__ */ import_react6.default.createElement(
      "button",
      {
        className: `p-2 ${isDark ? "bg-white/10 hover:bg-white/20" : "bg-black/70 hover:bg-black/90"} text-white border-none rounded-lg cursor-pointer flex items-center justify-center w-8 h-8 transition-colors duration-200 backdrop-blur-md ${isDark ? "shadow-[0_2px_8px_rgba(0,0,0,0.3)]" : "shadow-[0_2px_8px_rgba(0,0,0,0.2)]"} relative`,
        onMouseEnter: () => setIsButtonHovered(true),
        onMouseLeave: () => setIsButtonHovered(false),
        onClick,
        "aria-label": label
      },
      /* @__PURE__ */ import_react6.default.createElement(
        "svg",
        {
          xmlns: "http://www.w3.org/2000/svg",
          width: "16",
          height: "16",
          viewBox: "0 0 24 24",
          fill: "none",
          stroke: "currentColor",
          strokeWidth: "2",
          strokeLinecap: "round",
          strokeLinejoin: "round",
          className: "block"
        },
        icon
      ),
      showLabels && /* @__PURE__ */ import_react6.default.createElement(
        "span",
        {
          className: `${tooltipClasses.join(" ")} ${isButtonHovered ? "opacity-100" : "opacity-0"}`
        },
        label
      )
    );
  }, "IconButton");
  const formatValue = /* @__PURE__ */ __name((value) => {
    if (value === null) return "null";
    if (value === void 0) return "undefined";
    if (typeof value === "object") {
      try {
        return JSON.stringify(value, null, 2);
      } catch {
        return String(value);
      }
    }
    return String(value);
  }, "formatValue");
  const formatUserAgent = /* @__PURE__ */ __name((ua) => {
    if (!ua) return "N/A";
    return `${ua.device?.type || "unknown"}`;
  }, "formatUserAgent");
  const formatSafeArea = /* @__PURE__ */ __name((sa) => {
    if (!sa?.insets) return "N/A";
    const { top, bottom, left, right } = sa.insets;
    return `T:${top} B:${bottom} L:${left} R:${right}`;
  }, "formatSafeArea");
  return /* @__PURE__ */ import_react6.default.createElement(import_react6.default.Fragment, null, /* @__PURE__ */ import_react6.default.createElement(
    "div",
    {
      ref: containerRef,
      className: `${className} relative h-fit`,
      onMouseEnter: () => !attachTo && setIsHovered(true),
      onMouseLeave: () => !attachTo && setIsHovered(false)
    },
    /* @__PURE__ */ import_react6.default.createElement(
      "div",
      {
        className: getPositionClasses().join(" "),
        style: getPositionOffsetStyles()
      },
      !isInInspector && /* @__PURE__ */ import_react6.default.createElement(import_react6.default.Fragment, null, !isFullscreen && !isPip && /* @__PURE__ */ import_react6.default.createElement(import_react6.default.Fragment, null, (viewControls === true || viewControls === "fullscreen") && /* @__PURE__ */ import_react6.default.createElement(IconButton, { onClick: handleFullscreen, label: "Fullscreen" }, /* @__PURE__ */ import_react6.default.createElement("path", { d: "M15 3h6v6" }), /* @__PURE__ */ import_react6.default.createElement("path", { d: "m21 3-7 7" }), /* @__PURE__ */ import_react6.default.createElement("path", { d: "m3 21 7-7" }), /* @__PURE__ */ import_react6.default.createElement("path", { d: "M9 21H3v-6" })), (viewControls === true || viewControls === "pip") && /* @__PURE__ */ import_react6.default.createElement(IconButton, { onClick: handlePip, label: "Picture in Picture" }, /* @__PURE__ */ import_react6.default.createElement("path", { d: "M21 9V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v10c0 1.1.9 2 2 2h4" }), /* @__PURE__ */ import_react6.default.createElement("rect", { width: "10", height: "7", x: "12", y: "13", rx: "2" }))), enableDebugger && /* @__PURE__ */ import_react6.default.createElement(IconButton, { onClick: handleToggleOverlay, label: "Debug Info" }, /* @__PURE__ */ import_react6.default.createElement("path", { d: "M12 20v-9" }), /* @__PURE__ */ import_react6.default.createElement("path", { d: "M14 7a4 4 0 0 1 4 4v3a6 6 0 0 1-12 0v-3a4 4 0 0 1 4-4z" }), /* @__PURE__ */ import_react6.default.createElement("path", { d: "M14.12 3.88 16 2" }), /* @__PURE__ */ import_react6.default.createElement("path", { d: "M21 21a4 4 0 0 0-3.81-4" }), /* @__PURE__ */ import_react6.default.createElement("path", { d: "M21 5a4 4 0 0 1-3.55 3.97" }), /* @__PURE__ */ import_react6.default.createElement("path", { d: "M22 13h-4" }), /* @__PURE__ */ import_react6.default.createElement("path", { d: "M3 21a4 4 0 0 1 3.81-4" }), /* @__PURE__ */ import_react6.default.createElement("path", { d: "M3 5a4 4 0 0 0 3.55 3.97" }), /* @__PURE__ */ import_react6.default.createElement("path", { d: "M6 13H2" }), /* @__PURE__ */ import_react6.default.createElement("path", { d: "m8 2 1.88 1.88" }), /* @__PURE__ */ import_react6.default.createElement("path", { d: "M9 7.13V6a3 3 0 1 1 6 0v1.13" })))
    ),
    children
  ), isOverlayOpen && enableDebugger && /* @__PURE__ */ import_react6.default.createElement(
    "div",
    {
      ref: overlayRef,
      className: "fixed inset-0 bg-black text-white font-mono text-xs z-[10000] overflow-auto p-4",
      onClick: (e) => {
        if (e.target === overlayRef.current) {
          setIsOverlayOpen(false);
        }
      }
    },
    /* @__PURE__ */ import_react6.default.createElement(
      "button",
      {
        onClick: () => setIsOverlayOpen(false),
        className: "absolute top-4 right-4 bg-white/10 text-white border-none rounded w-8 h-8 cursor-pointer flex items-center justify-center text-lg leading-none",
        "aria-label": "Close"
      },
      "\xD7"
    ),
    /* @__PURE__ */ import_react6.default.createElement("div", { className: "max-w-[1200px] mx-auto pt-10" }, /* @__PURE__ */ import_react6.default.createElement("h1", { className: "text-lg font-bold mb-4 border-b border-gray-700 pb-2" }, "Debug Info"), /* @__PURE__ */ import_react6.default.createElement("table", { className: "w-full border-collapse border-spacing-0" }, /* @__PURE__ */ import_react6.default.createElement("tbody", null, /* @__PURE__ */ import_react6.default.createElement("tr", { className: "border-b border-gray-700" }, /* @__PURE__ */ import_react6.default.createElement("td", { className: "p-2 font-bold w-[200px] align-top" }, "Props"), /* @__PURE__ */ import_react6.default.createElement("td", { className: "p-2 whitespace-pre-wrap break-all" }, formatValue(props))), /* @__PURE__ */ import_react6.default.createElement("tr", { className: "border-b border-gray-700" }, /* @__PURE__ */ import_react6.default.createElement("td", { className: "p-2 font-bold w-[200px] align-top" }, "Output"), /* @__PURE__ */ import_react6.default.createElement("td", { className: "p-2 whitespace-pre-wrap break-all" }, formatValue(output))), /* @__PURE__ */ import_react6.default.createElement("tr", { className: "border-b border-gray-700" }, /* @__PURE__ */ import_react6.default.createElement("td", { className: "p-2 font-bold w-[200px] align-top" }, "Metadata"), /* @__PURE__ */ import_react6.default.createElement("td", { className: "p-2 whitespace-pre-wrap break-all" }, formatValue(metadata))), /* @__PURE__ */ import_react6.default.createElement("tr", { className: "border-b border-gray-700" }, /* @__PURE__ */ import_react6.default.createElement("td", { className: "p-2 font-bold w-[200px] align-top" }, "State"), /* @__PURE__ */ import_react6.default.createElement("td", { className: "p-2 whitespace-pre-wrap break-all" }, formatValue(state))), /* @__PURE__ */ import_react6.default.createElement("tr", { className: "border-b border-gray-700" }, /* @__PURE__ */ import_react6.default.createElement("td", { className: "p-2 font-bold w-[200px] align-top" }, "Theme"), /* @__PURE__ */ import_react6.default.createElement("td", { className: "p-2" }, theme)), /* @__PURE__ */ import_react6.default.createElement("tr", { className: "border-b border-gray-700" }, /* @__PURE__ */ import_react6.default.createElement("td", { className: "p-2 font-bold w-[200px] align-top" }, "Display Mode"), /* @__PURE__ */ import_react6.default.createElement("td", { className: "p-2" }, displayMode)), /* @__PURE__ */ import_react6.default.createElement("tr", { className: "border-b border-gray-700" }, /* @__PURE__ */ import_react6.default.createElement("td", { className: "p-2 font-bold w-[200px] align-top" }, "Locale"), /* @__PURE__ */ import_react6.default.createElement("td", { className: "p-2" }, locale)), /* @__PURE__ */ import_react6.default.createElement("tr", { className: "border-b border-gray-700" }, /* @__PURE__ */ import_react6.default.createElement("td", { className: "p-2 font-bold w-[200px] align-top" }, "Max Height"), /* @__PURE__ */ import_react6.default.createElement("td", { className: "p-2" }, maxHeight, "px")), /* @__PURE__ */ import_react6.default.createElement("tr", { className: "border-b border-gray-700" }, /* @__PURE__ */ import_react6.default.createElement("td", { className: "p-2 font-bold w-[200px] align-top" }, "User Agent"), /* @__PURE__ */ import_react6.default.createElement("td", { className: "p-2" }, formatUserAgent(userAgent))), /* @__PURE__ */ import_react6.default.createElement("tr", { className: "border-b border-gray-700" }, /* @__PURE__ */ import_react6.default.createElement("td", { className: "p-2 font-bold w-[200px] align-top" }, "Safe Area"), /* @__PURE__ */ import_react6.default.createElement("td", { className: "p-2" }, formatSafeArea(safeArea))), /* @__PURE__ */ import_react6.default.createElement("tr", { className: "border-b border-gray-700" }, /* @__PURE__ */ import_react6.default.createElement("td", { className: "p-2 font-bold w-[200px] align-top" }, "API Available"), /* @__PURE__ */ import_react6.default.createElement("td", { className: "p-2" }, isAvailable ? "Yes" : "No")), /* @__PURE__ */ import_react6.default.createElement("tr", { className: "border-b border-gray-700" }, /* @__PURE__ */ import_react6.default.createElement("td", { className: "p-2 font-bold w-[200px] align-top" }, "window.openai Keys"), /* @__PURE__ */ import_react6.default.createElement("td", { className: "p-2" }, windowOpenAiKeys.length > 0 ? windowOpenAiKeys.join(", ") : "N/A")))), /* @__PURE__ */ import_react6.default.createElement("h2", { className: "text-base font-bold mt-8 mb-4 border-b border-gray-700 pb-2" }, "Actions"), /* @__PURE__ */ import_react6.default.createElement("div", { className: "flex flex-col gap-3" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "flex gap-2 items-center" }, /* @__PURE__ */ import_react6.default.createElement(
      "input",
      {
        type: "text",
        value: toolName,
        onChange: (e) => setToolName(e.target.value),
        placeholder: "Tool name",
        className: "py-1.5 px-2 bg-[#1a1a1a] text-white border border-gray-700 rounded font-mono text-xs w-[150px]"
      }
    ), /* @__PURE__ */ import_react6.default.createElement(
      "input",
      {
        type: "text",
        value: toolArgs,
        onChange: (e) => setToolArgs(e.target.value),
        placeholder: '{"key": "value"}',
        className: "py-1.5 px-2 bg-[#1a1a1a] text-white border border-gray-700 rounded font-mono text-xs flex-1"
      }
    ), /* @__PURE__ */ import_react6.default.createElement(
      "button",
      {
        onClick: handleCallTool,
        className: "py-1.5 px-3 bg-gray-800 text-white border border-gray-600 rounded cursor-pointer font-mono text-xs"
      },
      "Call Tool"
    )), /* @__PURE__ */ import_react6.default.createElement("div", { className: "flex gap-2 items-center" }, /* @__PURE__ */ import_react6.default.createElement(
      "input",
      {
        type: "text",
        value: followUpMessage,
        onChange: (e) => setFollowUpMessage(e.target.value),
        placeholder: "Follow-up message",
        className: "py-1.5 px-2 bg-[#1a1a1a] text-white border border-gray-700 rounded font-mono text-xs flex-1"
      }
    ), /* @__PURE__ */ import_react6.default.createElement(
      "button",
      {
        onClick: handleSendFollowUpMessage,
        className: "py-1.5 px-3 bg-gray-800 text-white border border-gray-600 rounded cursor-pointer font-mono text-xs"
      },
      "Send Follow-Up"
    )), /* @__PURE__ */ import_react6.default.createElement("div", { className: "flex gap-2 items-center" }, /* @__PURE__ */ import_react6.default.createElement(
      "input",
      {
        type: "text",
        value: externalUrl,
        onChange: (e) => setExternalUrl(e.target.value),
        placeholder: "External URL",
        className: "py-1.5 px-2 bg-[#1a1a1a] text-white border border-gray-700 rounded font-mono text-xs flex-1"
      }
    ), /* @__PURE__ */ import_react6.default.createElement(
      "button",
      {
        onClick: handleOpenExternal,
        className: "py-1.5 px-3 bg-gray-800 text-white border border-gray-600 rounded cursor-pointer font-mono text-xs"
      },
      "Open Link"
    )), /* @__PURE__ */ import_react6.default.createElement("div", { className: "flex gap-2 items-center" }, /* @__PURE__ */ import_react6.default.createElement("span", { className: "w-[150px] text-xs" }, "Display Mode:"), /* @__PURE__ */ import_react6.default.createElement(
      "button",
      {
        onClick: () => handleRequestDisplayMode("inline"),
        className: "py-1.5 px-3 bg-gray-800 text-white border border-gray-600 rounded cursor-pointer font-mono text-xs flex-1"
      },
      "Inline"
    ), /* @__PURE__ */ import_react6.default.createElement(
      "button",
      {
        onClick: () => handleRequestDisplayMode("pip"),
        className: "py-1.5 px-3 bg-gray-800 text-white border border-gray-600 rounded cursor-pointer font-mono text-xs flex-1"
      },
      "PiP"
    ), /* @__PURE__ */ import_react6.default.createElement(
      "button",
      {
        onClick: () => handleRequestDisplayMode("fullscreen"),
        className: "py-1.5 px-3 bg-gray-800 text-white border border-gray-600 rounded cursor-pointer font-mono text-xs flex-1"
      },
      "Fullscreen"
    )), /* @__PURE__ */ import_react6.default.createElement("div", { className: "flex gap-2 items-center" }, /* @__PURE__ */ import_react6.default.createElement(
      "button",
      {
        onClick: handleSetState,
        className: "py-1.5 px-3 bg-gray-800 text-white border border-gray-600 rounded cursor-pointer font-mono text-xs"
      },
      "Set State (Add Timestamp)"
    )), actionResult && /* @__PURE__ */ import_react6.default.createElement("div", { className: "mt-2 p-2 bg-[#1a1a1a] border border-gray-700 rounded whitespace-pre-wrap break-all text-[11px] max-h-[200px] overflow-auto" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "font-bold mb-1 text-gray-400" }, "Result:"), actionResult, /* @__PURE__ */ import_react6.default.createElement(
      "button",
      {
        onClick: () => setActionResult(""),
        className: "mt-2 py-1 px-2 bg-gray-800 text-white border border-gray-600 rounded cursor-pointer font-mono text-[11px]"
      },
      "Clear"
    ))))
  ));
}
__name(WidgetControls, "WidgetControls");

// src/react/McpUseProvider.tsx
var import_react7 = __toESM(require("react"), 1);
function getBasename() {
  if (typeof window === "undefined") return "/";
  const path2 = window.location.pathname;
  const match = path2.match(/^(\/inspector\/api\/dev-widget\/[^/]+)/);
  if (match) {
    return match[1];
  }
  return "/";
}
__name(getBasename, "getBasename");
var HEIGHT_DEBOUNCE_MS = 150;
var MIN_HEIGHT_CHANGE_PX = 5;
function McpUseProvider({
  children,
  debugger: enableDebugger = false,
  viewControls = false,
  autoSize = false
}) {
  const basename = getBasename();
  const containerRef = (0, import_react7.useRef)(null);
  const lastHeightRef = (0, import_react7.useRef)(0);
  const debounceTimeoutRef = (0, import_react7.useRef)(null);
  const notificationInProgressRef = (0, import_react7.useRef)(false);
  const [BrowserRouter, setBrowserRouter] = (0, import_react7.useState)(null);
  const [routerError, setRouterError] = (0, import_react7.useState)(null);
  const [isRouterLoading, setIsRouterLoading] = (0, import_react7.useState)(true);
  (0, import_react7.useEffect)(() => {
    let mounted = true;
    (async () => {
      try {
        const routerModule = await import("react-router");
        if (mounted) {
          setBrowserRouter(() => routerModule.BrowserRouter);
          setIsRouterLoading(false);
        }
      } catch (error) {
        if (mounted) {
          setRouterError(
            new Error(
              "\u274C react-router not installed!\n\nTo use MCP widgets with McpUseProvider, you need to install:\n\n  npm install react-router\n  # or\n  pnpm add react-router\n\nThis dependency is automatically included in projects created with 'create-mcp-use-app'."
            )
          );
          setIsRouterLoading(false);
        }
      }
    })();
    return () => {
      mounted = false;
    };
  }, []);
  const notifyHeight = (0, import_react7.useCallback)((height) => {
    if (typeof window !== "undefined" && window.openai?.notifyIntrinsicHeight) {
      notificationInProgressRef.current = true;
      window.openai.notifyIntrinsicHeight(height).then(() => {
        notificationInProgressRef.current = false;
      }).catch((error) => {
        notificationInProgressRef.current = false;
        console.error(
          "[McpUseProvider] Failed to notify intrinsic height:",
          error
        );
      });
    }
  }, []);
  const debouncedNotifyHeight = (0, import_react7.useCallback)(
    (height) => {
      if (debounceTimeoutRef.current) {
        clearTimeout(debounceTimeoutRef.current);
      }
      debounceTimeoutRef.current = setTimeout(() => {
        const heightDiff = Math.abs(height - lastHeightRef.current);
        if (heightDiff >= MIN_HEIGHT_CHANGE_PX && height > 0) {
          lastHeightRef.current = height;
          notifyHeight(height);
        }
      }, HEIGHT_DEBOUNCE_MS);
    },
    [notifyHeight]
  );
  (0, import_react7.useEffect)(() => {
    if (!autoSize) {
      return;
    }
    const container = containerRef.current;
    if (!container || typeof ResizeObserver === "undefined") {
      return;
    }
    const observer = new ResizeObserver((entries) => {
      if (notificationInProgressRef.current) {
        return;
      }
      for (const entry of entries) {
        const height = entry.contentRect.height;
        const scrollHeight = entry.target.scrollHeight;
        const intrinsicHeight = Math.max(height, scrollHeight);
        debouncedNotifyHeight(intrinsicHeight);
      }
    });
    observer.observe(container);
    const initialHeight = Math.max(
      container.offsetHeight,
      container.scrollHeight
    );
    if (initialHeight > 0) {
      debouncedNotifyHeight(initialHeight);
    }
    return () => {
      observer.disconnect();
      if (debounceTimeoutRef.current) {
        clearTimeout(debounceTimeoutRef.current);
        debounceTimeoutRef.current = null;
      }
      notificationInProgressRef.current = false;
    };
  }, [autoSize, debouncedNotifyHeight]);
  if (isRouterLoading) {
    return /* @__PURE__ */ import_react7.default.createElement(import_react7.StrictMode, null, /* @__PURE__ */ import_react7.default.createElement(ThemeProvider, null, /* @__PURE__ */ import_react7.default.createElement("div", { style: { padding: "20px", textAlign: "center" } }, "Loading...")));
  }
  if (routerError) {
    throw routerError;
  }
  let content = children;
  content = /* @__PURE__ */ import_react7.default.createElement(ErrorBoundary, null, content);
  if (enableDebugger || viewControls) {
    content = /* @__PURE__ */ import_react7.default.createElement(WidgetControls, { debugger: enableDebugger, viewControls }, content);
  }
  if (BrowserRouter) {
    content = /* @__PURE__ */ import_react7.default.createElement(BrowserRouter, { basename }, content);
  }
  content = /* @__PURE__ */ import_react7.default.createElement(ThemeProvider, null, content);
  if (autoSize) {
    const containerStyle = {
      width: "100%",
      minHeight: 0
    };
    content = /* @__PURE__ */ import_react7.default.createElement("div", { ref: containerRef, style: containerStyle }, content);
  }
  return /* @__PURE__ */ import_react7.default.createElement(import_react7.StrictMode, null, content);
}
__name(McpUseProvider, "McpUseProvider");

// src/react/McpClientProvider.tsx
var import_react8 = __toESM(require("react"), 1);
var McpClientContext = (0, import_react8.createContext)(null);
var MAX_NOTIFICATIONS = 500;
function McpServerWrapper({
  id,
  options,
  onUpdate,
  rpcWrapTransport,
  onGlobalSamplingRequest,
  onGlobalElicitationRequest
}) {
  const {
    name,
    onSamplingRequest,
    onElicitationRequest,
    onNotificationReceived,
    wrapTransport: optionsWrapTransport
  } = options;
  const mcpOptions = (0, import_react8.useMemo)(() => {
    const {
      name: _name,
      onSamplingRequest: _onSamplingRequest,
      onElicitationRequest: _onElicitationRequest,
      onNotificationReceived: _onNotificationReceived,
      wrapTransport: _wrapTransport,
      ...rest
    } = options;
    return rest;
  }, [options]);
  const combinedWrapTransport = (0, import_react8.useMemo)(() => {
    if (!rpcWrapTransport && !optionsWrapTransport) return void 0;
    return (transport) => {
      let wrapped = transport;
      if (rpcWrapTransport) {
        wrapped = rpcWrapTransport(wrapped, id);
      }
      if (optionsWrapTransport) {
        wrapped = optionsWrapTransport(wrapped, id);
      }
      return wrapped;
    };
  }, [rpcWrapTransport, optionsWrapTransport, id]);
  const [notifications, setNotifications] = (0, import_react8.useState)([]);
  const [pendingSamplingRequests, setPendingSamplingRequests] = (0, import_react8.useState)([]);
  const samplingIdCounter = (0, import_react8.useRef)(0);
  const [pendingElicitationRequests, setPendingElicitationRequests] = (0, import_react8.useState)([]);
  const elicitationIdCounter = (0, import_react8.useRef)(0);
  const markNotificationRead = (0, import_react8.useCallback)((notificationId) => {
    setNotifications(
      (prev) => prev.map((n) => n.id === notificationId ? { ...n, read: true } : n)
    );
  }, []);
  const markAllNotificationsRead = (0, import_react8.useCallback)(() => {
    setNotifications((prev) => prev.map((n) => ({ ...n, read: true })));
  }, []);
  const clearNotifications = (0, import_react8.useCallback)(() => {
    setNotifications([]);
  }, []);
  const handleNotification = (0, import_react8.useCallback)(
    (notification) => {
      const mcpNotification = {
        id: globalThis.crypto?.randomUUID?.() || `${Date.now()}-${Math.random()}`,
        method: notification.method,
        params: notification.params,
        timestamp: Date.now(),
        read: false
      };
      setNotifications((prev) => {
        const updated = [mcpNotification, ...prev];
        if (updated.length > MAX_NOTIFICATIONS) {
          return updated.slice(0, MAX_NOTIFICATIONS);
        }
        return updated;
      });
      onNotificationReceived?.(mcpNotification);
    },
    [onNotificationReceived]
  );
  const approveSampling = (0, import_react8.useCallback)(
    (requestId, result) => {
      setPendingSamplingRequests((prev) => {
        const request = prev.find((r) => r.id === requestId);
        if (request) {
          request.resolve(result);
          return prev.filter((r) => r.id !== requestId);
        }
        return prev;
      });
    },
    []
  );
  const rejectSampling = (0, import_react8.useCallback)((requestId, error) => {
    setPendingSamplingRequests((prev) => {
      const request = prev.find((r) => r.id === requestId);
      if (request) {
        request.reject(new Error(error || "User rejected sampling request"));
        return prev.filter((r) => r.id !== requestId);
      }
      return prev;
    });
  }, []);
  const samplingCallback = (0, import_react8.useCallback)(
    async (params) => {
      return new Promise((resolve, reject) => {
        const requestId = `sampling-${samplingIdCounter.current++}`;
        const request = {
          id: requestId,
          request: { method: "sampling/createMessage", params },
          timestamp: Date.now(),
          serverName: name || id
        };
        const newRequest = {
          ...request,
          resolve,
          reject
        };
        setPendingSamplingRequests((prev) => [...prev, newRequest]);
        onSamplingRequest?.(request);
        onGlobalSamplingRequest?.(
          request,
          id,
          name || id,
          approveSampling,
          rejectSampling
        );
      });
    },
    [
      id,
      name,
      onSamplingRequest,
      onGlobalSamplingRequest,
      approveSampling,
      rejectSampling
    ]
  );
  const approveElicitation = (0, import_react8.useCallback)(
    (requestId, result) => {
      setPendingElicitationRequests((prev) => {
        const request = prev.find((r) => r.id === requestId);
        if (request) {
          request.resolve(result);
          return prev.filter((r) => r.id !== requestId);
        }
        return prev;
      });
    },
    []
  );
  const rejectElicitation = (0, import_react8.useCallback)((requestId, error) => {
    setPendingElicitationRequests((prev) => {
      const request = prev.find((r) => r.id === requestId);
      if (request) {
        request.reject(new Error(error || "User rejected elicitation request"));
        return prev.filter((r) => r.id !== requestId);
      }
      return prev;
    });
  }, []);
  const elicitationCallback = (0, import_react8.useCallback)(
    async (params) => {
      return new Promise((resolve, reject) => {
        const requestId = `elicitation-${elicitationIdCounter.current++}`;
        const request = {
          id: requestId,
          request: params,
          timestamp: Date.now(),
          serverName: name || id
        };
        const newRequest = {
          ...request,
          resolve,
          reject
        };
        setPendingElicitationRequests((prev) => [...prev, newRequest]);
        onElicitationRequest?.(request);
        onGlobalElicitationRequest?.(
          request,
          id,
          name || id,
          approveElicitation,
          rejectElicitation
        );
      });
    },
    [
      id,
      name,
      onElicitationRequest,
      onGlobalElicitationRequest,
      approveElicitation,
      rejectElicitation
    ]
  );
  const mcp = useMcp({
    ...mcpOptions,
    onNotification: handleNotification,
    samplingCallback,
    onElicitation: elicitationCallback,
    wrapTransport: combinedWrapTransport
  });
  const publicSamplingRequests = (0, import_react8.useMemo)(
    () => pendingSamplingRequests.map((r) => ({
      id: r.id,
      request: r.request,
      timestamp: r.timestamp,
      serverName: r.serverName
    })),
    [pendingSamplingRequests]
  );
  const publicElicitationRequests = (0, import_react8.useMemo)(
    () => pendingElicitationRequests.map((r) => ({
      id: r.id,
      request: r.request,
      timestamp: r.timestamp,
      serverName: r.serverName
    })),
    [pendingElicitationRequests]
  );
  const unreadNotificationCount = (0, import_react8.useMemo)(
    () => notifications.filter((n) => !n.read).length,
    [notifications]
  );
  const onUpdateRef = (0, import_react8.useRef)(onUpdate);
  const prevServerRef = (0, import_react8.useRef)(null);
  (0, import_react8.useEffect)(() => {
    onUpdateRef.current = onUpdate;
  }, [onUpdate]);
  (0, import_react8.useEffect)(() => {
    const server = {
      ...mcp,
      id,
      url: options.url || "",
      name: name || id,
      notifications,
      unreadNotificationCount,
      markNotificationRead,
      markAllNotificationsRead,
      clearNotifications,
      pendingSamplingRequests: publicSamplingRequests,
      approveSampling,
      rejectSampling,
      pendingElicitationRequests: publicElicitationRequests,
      approveElicitation,
      rejectElicitation
    };
    const prevServer = prevServerRef.current;
    if (!prevServer || prevServer.state !== server.state || prevServer.error !== server.error || prevServer.authUrl !== server.authUrl || prevServer.tools.length !== server.tools.length || prevServer.resources.length !== server.resources.length || prevServer.prompts.length !== server.prompts.length || prevServer.serverInfo !== server.serverInfo || prevServer.capabilities !== server.capabilities || prevServer.notifications.length !== server.notifications.length || prevServer.unreadNotificationCount !== server.unreadNotificationCount || prevServer.pendingSamplingRequests.length !== server.pendingSamplingRequests.length || prevServer.pendingElicitationRequests.length !== server.pendingElicitationRequests.length || !prevServer.client) {
      prevServerRef.current = server;
      onUpdateRef.current(server);
    }
  }, [
    id,
    name,
    options.url,
    // Primitive values that indicate meaningful state changes
    mcp.state,
    mcp.error,
    mcp.authUrl,
    // Use array LENGTHS instead of array references to avoid triggering on reference changes
    mcp.tools.length,
    mcp.resources.length,
    mcp.resourceTemplates.length,
    mcp.prompts.length,
    // Objects excluded - manual comparison handles serverInfo/capabilities changes
    // Functions excluded - they're stable via useCallback in useMcp
    // mcp.log excluded - log changes shouldn't trigger provider updates
    // mcp.client excluded - client reference stability handled by manual check
    notifications.length,
    unreadNotificationCount,
    publicSamplingRequests.length,
    publicElicitationRequests.length,
    // Callback functions are stable via useCallback
    markNotificationRead,
    markAllNotificationsRead,
    clearNotifications,
    approveSampling,
    rejectSampling,
    approveElicitation,
    rejectElicitation
  ]);
  return null;
}
__name(McpServerWrapper, "McpServerWrapper");
function McpClientProvider({
  children,
  mcpServers,
  storageProvider,
  enableRpcLogging = false,
  onServerAdded,
  onServerRemoved,
  onServerStateChange,
  onSamplingRequest,
  onElicitationRequest
}) {
  const [serverConfigs, setServerConfigs] = (0, import_react8.useState)([]);
  const [servers, setServers] = (0, import_react8.useState)([]);
  const [storageLoaded, setStorageLoaded] = (0, import_react8.useState)(false);
  const [rpcWrapTransport, setRpcWrapTransport] = (0, import_react8.useState)(void 0);
  const [rpcLoggingReady, setRpcLoggingReady] = (0, import_react8.useState)(false);
  (0, import_react8.useEffect)(() => {
    if (!enableRpcLogging || typeof window === "undefined") {
      setRpcWrapTransport(void 0);
      setRpcLoggingReady(true);
      return;
    }
    Promise.resolve().then(() => (init_rpc_logger(), rpc_logger_exports)).then((module2) => {
      console.log("[McpClientProvider] RPC logger loaded");
      setRpcWrapTransport(() => module2.wrapTransportForLogging);
      setRpcLoggingReady(true);
    }).catch((err) => {
      console.error("[McpClientProvider] Failed to load RPC logger:", err);
      setRpcWrapTransport(void 0);
      setRpcLoggingReady(true);
    });
  }, [enableRpcLogging]);
  (0, import_react8.useEffect)(() => {
    if (!rpcLoggingReady) {
      console.log(
        "[McpClientProvider] Waiting for RPC logging to be ready before loading servers"
      );
      return;
    }
    const loadServers = /* @__PURE__ */ __name(async () => {
      console.log(
        "[McpClientProvider] Loading servers, storageProvider:",
        !!storageProvider,
        "mcpServers:",
        mcpServers
      );
      if (!storageProvider) {
        if (mcpServers) {
          const configs = Object.entries(mcpServers).map(([id, options]) => ({
            id,
            options
          }));
          console.log(
            "[McpClientProvider] Loaded from mcpServers prop:",
            configs.length
          );
          setServerConfigs(configs);
        }
        setStorageLoaded(true);
        return;
      }
      try {
        const storedServers = await Promise.resolve(
          storageProvider.getServers()
        );
        console.log(
          "[McpClientProvider] Loaded from storage:",
          Object.keys(storedServers).length
        );
        const mergedServers = { ...storedServers, ...mcpServers };
        const configs = Object.entries(mergedServers).map(([id, options]) => ({
          id,
          options
        }));
        console.log(
          "[McpClientProvider] Total servers after merge:",
          configs.length
        );
        setServerConfigs(configs);
        setStorageLoaded(true);
      } catch (error) {
        console.error(
          "[McpClientProvider] Failed to load from storage:",
          error
        );
        if (mcpServers) {
          const configs = Object.entries(mcpServers).map(([id, options]) => ({
            id,
            options
          }));
          setServerConfigs(configs);
        }
        setStorageLoaded(true);
      }
    }, "loadServers");
    loadServers();
  }, [storageProvider, mcpServers, rpcLoggingReady]);
  (0, import_react8.useEffect)(() => {
    if (!storageProvider || !storageLoaded) return;
    const saveServers = /* @__PURE__ */ __name(async () => {
      try {
        const serversToSave = serverConfigs.reduce(
          (acc, config) => {
            acc[config.id] = config.options;
            return acc;
          },
          {}
        );
        await Promise.resolve(storageProvider.setServers(serversToSave));
      } catch (error) {
        console.error("[McpClientProvider] Failed to save to storage:", error);
      }
    }, "saveServers");
    saveServers();
  }, [serverConfigs, storageProvider, storageLoaded]);
  const handleServerUpdate = (0, import_react8.useCallback)(
    (updatedServer) => {
      setServers((prev) => {
        const index = prev.findIndex((s) => s.id === updatedServer.id);
        const isNewServer = index === -1;
        if (isNewServer) {
          onServerAdded?.(updatedServer.id, updatedServer);
          return [...prev, updatedServer];
        }
        const current = prev[index];
        const stateChanged = current.state !== updatedServer.state;
        if (current.state === updatedServer.state && current.tools === updatedServer.tools && current.resources === updatedServer.resources && current.prompts === updatedServer.prompts && current.error === updatedServer.error && current.serverInfo === updatedServer.serverInfo && current.client === updatedServer.client && current.notifications === updatedServer.notifications && current.unreadNotificationCount === updatedServer.unreadNotificationCount && current.pendingSamplingRequests.length === updatedServer.pendingSamplingRequests.length && current.pendingElicitationRequests.length === updatedServer.pendingElicitationRequests.length) {
          return prev;
        }
        if (stateChanged) {
          onServerStateChange?.(updatedServer.id, updatedServer.state);
        }
        const newServers = [...prev];
        newServers[index] = updatedServer;
        return newServers;
      });
    },
    [onServerAdded, onServerStateChange]
  );
  const addServer = (0, import_react8.useCallback)((id, options) => {
    console.log("[McpClientProvider] addServer called:", id, options);
    setServerConfigs((prev) => {
      if (prev.find((s) => s.id === id)) {
        console.warn(
          `[McpClientProvider] Server with id "${id}" already exists`
        );
        return prev;
      }
      console.log("[McpClientProvider] Adding new server to configs:", id);
      return [...prev, { id, options }];
    });
  }, []);
  const removeServer = (0, import_react8.useCallback)(
    (id) => {
      setServers((prev) => {
        const server = prev.find((s) => s.id === id);
        if (server?.disconnect) {
          server.disconnect();
        }
        if (server?.clearStorage) {
          server.clearStorage();
        }
        return prev.filter((s) => s.id !== id);
      });
      setServerConfigs((prev) => prev.filter((s) => s.id !== id));
      onServerRemoved?.(id);
    },
    [onServerRemoved]
  );
  const updateServer = (0, import_react8.useCallback)(
    async (id, options) => {
      return new Promise((resolve) => {
        const currentConfig = serverConfigs.find((s) => s.id === id);
        if (!currentConfig) {
          console.warn(
            `[McpClientProvider] Cannot update server "${id}" - not found`
          );
          resolve();
          return;
        }
        const updatedOptions = {
          ...currentConfig.options,
          ...options
        };
        setServers((prev) => {
          const server = prev.find((s) => s.id === id);
          if (server?.disconnect) {
            server.disconnect();
          }
          if (server?.clearStorage) {
            server.clearStorage();
          }
          return prev.filter((s) => s.id !== id);
        });
        setServerConfigs((prev) => {
          const updated = prev.map(
            (s) => s.id === id ? { id, options: updatedOptions } : s
          );
          setTimeout(() => resolve(), 0);
          return updated;
        });
      });
    },
    [serverConfigs]
  );
  const getServer = (0, import_react8.useCallback)(
    (id) => {
      return servers.find((s) => s.id === id);
    },
    [servers]
  );
  const contextValue = (0, import_react8.useMemo)(
    () => ({
      servers,
      addServer,
      removeServer,
      updateServer,
      getServer,
      storageLoaded
    }),
    [servers, addServer, removeServer, updateServer, getServer, storageLoaded]
  );
  return /* @__PURE__ */ import_react8.default.createElement(McpClientContext.Provider, { value: contextValue }, children, serverConfigs.map((config) => /* @__PURE__ */ import_react8.default.createElement(
    McpServerWrapper,
    {
      key: config.id,
      id: config.id,
      options: config.options,
      onUpdate: handleServerUpdate,
      rpcWrapTransport,
      onGlobalSamplingRequest: onSamplingRequest,
      onGlobalElicitationRequest: onElicitationRequest
    }
  )));
}
__name(McpClientProvider, "McpClientProvider");
function useMcpClient() {
  const context = (0, import_react8.useContext)(McpClientContext);
  if (!context) {
    throw new Error("useMcpClient must be used within a McpClientProvider");
  }
  return context;
}
__name(useMcpClient, "useMcpClient");
function useMcpServer(id) {
  const { getServer } = useMcpClient();
  return getServer(id);
}
__name(useMcpServer, "useMcpServer");

// src/react/storage/LocalStorageProvider.ts
var LocalStorageProvider = class {
  constructor(storageKey = "mcp-client-servers") {
    this.storageKey = storageKey;
  }
  static {
    __name(this, "LocalStorageProvider");
  }
  getServers() {
    try {
      const stored = localStorage.getItem(this.storageKey);
      return stored ? JSON.parse(stored) : {};
    } catch (error) {
      console.error("[LocalStorageProvider] Failed to load servers:", error);
      return {};
    }
  }
  setServers(servers) {
    try {
      localStorage.setItem(this.storageKey, JSON.stringify(servers));
    } catch (error) {
      console.error("[LocalStorageProvider] Failed to save servers:", error);
    }
  }
  setServer(id, config) {
    const servers = this.getServers();
    servers[id] = config;
    this.setServers(servers);
  }
  removeServer(id) {
    const servers = this.getServers();
    delete servers[id];
    this.setServers(servers);
  }
  clear() {
    try {
      localStorage.removeItem(this.storageKey);
    } catch (error) {
      console.error("[LocalStorageProvider] Failed to clear:", error);
    }
  }
};

// src/react/storage/MemoryStorageProvider.ts
var MemoryStorageProvider = class {
  static {
    __name(this, "MemoryStorageProvider");
  }
  storage = {};
  getServers() {
    return { ...this.storage };
  }
  setServers(servers) {
    this.storage = { ...servers };
  }
  setServer(id, config) {
    this.storage[id] = config;
  }
  removeServer(id) {
    delete this.storage[id];
  }
  clear() {
    this.storage = {};
  }
};

// src/react/index.ts
init_rpc_logger();

// src/agents/prompts/index.ts
init_codeMode();
var PROMPTS = {
  CODE_MODE: CODE_MODE_AGENT_PROMPT
};

// index.ts
init_client();

// src/errors.ts
var ElicitationValidationError = class _ElicitationValidationError extends Error {
  constructor(message, cause) {
    super(message);
    this.cause = cause;
    this.name = "ElicitationValidationError";
    if (Error.captureStackTrace) {
      Error.captureStackTrace(this, _ElicitationValidationError);
    }
  }
  static {
    __name(this, "ElicitationValidationError");
  }
};
var ElicitationTimeoutError = class _ElicitationTimeoutError extends Error {
  constructor(message, timeoutMs) {
    super(message);
    this.timeoutMs = timeoutMs;
    this.name = "ElicitationTimeoutError";
    if (Error.captureStackTrace) {
      Error.captureStackTrace(this, _ElicitationTimeoutError);
    }
  }
  static {
    __name(this, "ElicitationTimeoutError");
  }
};
var ElicitationDeclinedError = class _ElicitationDeclinedError extends Error {
  static {
    __name(this, "ElicitationDeclinedError");
  }
  constructor(message = "User declined the elicitation request") {
    super(message);
    this.name = "ElicitationDeclinedError";
    if (Error.captureStackTrace) {
      Error.captureStackTrace(this, _ElicitationDeclinedError);
    }
  }
};