// @bun
var __defProp = Object.defineProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, {
      get: all[name],
      enumerable: true,
      configurable: true,
      set: (newValue) => all[name] = () => newValue
    });
};
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
var __require = import.meta.require;

// src/tools/mcp-client-helpers.ts
import {
  Experimental_StdioMCPTransport as StdioClientTransport
} from "@ai-sdk/mcp/mcp-stdio";
function buildMcpTransport(config) {
  const transport = resolveTransportType(config);
  if (transport === "stdio") {
    const stdioConfig = resolveStdioConfig(config);
    return new StdioClientTransport(stdioConfig);
  }
  const remoteConfig = config;
  const headers = resolveRemoteHeaders(remoteConfig);
  const remoteTransport = {
    type: transport,
    url: requireNonEmptyString(remoteConfig.url, "url", config.name)
  };
  if (headers) {
    remoteTransport.headers = headers;
  }
  if (remoteConfig.authProvider) {
    remoteTransport.authProvider = remoteConfig.authProvider;
  }
  return remoteTransport;
}
function prefixToolNames(config, tools) {
  const prefix = config.toolPrefix?.trim();
  if (!prefix) {
    return tools;
  }
  const prefixedTools = {};
  for (const [toolName, tool] of Object.entries(tools)) {
    prefixedTools[`${prefix}_${toolName}`] = tool;
  }
  return prefixedTools;
}
function getErrorMessage(error) {
  if (error instanceof Error) {
    return error.message;
  }
  return String(error);
}
function resolveTransportType(config) {
  return config.transport ?? "stdio";
}
function resolveStdioConfig(config) {
  const stdioConfig = config;
  return {
    command: requireNonEmptyString(stdioConfig.command, "command", config.name),
    args: stdioConfig.args,
    env: stdioConfig.env,
    cwd: stdioConfig.cwd
  };
}
function resolveRemoteHeaders(config) {
  const headers = {
    ...config.headers ?? {}
  };
  const accessToken = config.accessToken ?? resolveEnvToken(config.accessTokenEnvVar);
  if (accessToken && headers.Authorization === undefined) {
    headers.Authorization = `Bearer ${accessToken}`;
  }
  return Object.keys(headers).length > 0 ? headers : undefined;
}
function resolveEnvToken(envVarName) {
  if (!envVarName) {
    return;
  }
  const value = process.env[envVarName];
  if (!value) {
    return;
  }
  const trimmed = value.trim();
  return trimmed.length > 0 ? trimmed : undefined;
}
function requireNonEmptyString(value, field, serverName) {
  if (!value) {
    throw new Error(`MCP server "${serverName}" is missing required "${field}".`);
  }
  const trimmed = value.trim();
  if (trimmed.length === 0) {
    throw new Error(`MCP server "${serverName}" has an empty "${field}".`);
  }
  return trimmed;
}
var init_mcp_client_helpers = () => {};

// src/tools/mcp-client.ts
import {
  experimental_createMCPClient
} from "@ai-sdk/mcp";
async function mcpServerToTools(config) {
  let client = null;
  try {
    const transport = buildMcpTransport(config);
    client = await experimental_createMCPClient({
      transport,
      name: config.clientName,
      version: config.clientVersion
    });
    const tools = await client.tools();
    const prefixedTools = prefixToolNames(config, tools);
    const connectedClient = client;
    return {
      tools: prefixedTools,
      cleanup: () => connectedClient.close(),
      serverToolNames: {
        [config.name]: Object.keys(prefixedTools)
      }
    };
  } catch (error) {
    if (client) {
      await client.close().catch(() => {
        return;
      });
    }
    throw new Error(`[MCP:${config.name}] Failed to connect tools: ${getErrorMessage(error)}`);
  }
}
async function createMcpToolsets(configs, options = {}) {
  const connected = [];
  try {
    for (const config of configs) {
      const result = await mcpServerToTools(config);
      connected.push(result);
    }
  } catch (error) {
    await Promise.allSettled(connected.map((result) => result.cleanup()));
    throw error;
  }
  const combinedTools = {};
  const serverToolNames = {};
  const collisionStrategy = options.onNameCollision ?? "overwrite";
  try {
    for (const result of connected) {
      for (const [serverName, toolNames] of Object.entries(result.serverToolNames)) {
        serverToolNames[serverName] = toolNames;
      }
      for (const [toolName, tool] of Object.entries(result.tools)) {
        const hasCollision = combinedTools[toolName] !== undefined;
        if (hasCollision && collisionStrategy === "error") {
          throw new Error(`Duplicate MCP tool name "${toolName}" detected. Use "toolPrefix" or set onNameCollision to "overwrite".`);
        }
        combinedTools[toolName] = tool;
      }
    }
  } catch (error) {
    await Promise.allSettled(connected.map((result) => result.cleanup()));
    throw error;
  }
  return {
    tools: combinedTools,
    serverToolNames,
    cleanup: async () => {
      const cleanupResults = await Promise.allSettled(connected.map((result) => result.cleanup()));
      const failures = cleanupResults.filter((result) => result.status === "rejected");
      if (failures.length > 0) {
        throw new Error(`Failed to cleanup ${failures.length} MCP client connection(s).`);
      }
    }
  };
}
var init_mcp_client = __esm(() => {
  init_mcp_client_helpers();
});
init_mcp_client();

export {
  mcpServerToTools,
  createMcpToolsets
};
