// @bun
var __create = Object.create;
var __getProtoOf = Object.getPrototypeOf;
var __defProp = Object.defineProperty;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __hasOwnProp = Object.prototype.hasOwnProperty;
function __accessProp(key) {
  return this[key];
}
var __toESMCache_node;
var __toESMCache_esm;
var __toESM = (mod, isNodeMode, target) => {
  var canCache = mod != null && typeof mod === "object";
  if (canCache) {
    var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
    var cached = cache.get(mod);
    if (cached)
      return cached;
  }
  target = mod != null ? __create(__getProtoOf(mod)) : {};
  const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
  for (let key of __getOwnPropNames(mod))
    if (!__hasOwnProp.call(to, key))
      __defProp(to, key, {
        get: __accessProp.bind(mod, key),
        enumerable: true
      });
  if (canCache)
    cache.set(mod, to);
  return to;
};
var __toCommonJS = (from) => {
  var entry = (__moduleCache ??= new WeakMap).get(from), desc;
  if (entry)
    return entry;
  entry = __defProp({}, "__esModule", { value: true });
  if (from && typeof from === "object" || typeof from === "function") {
    for (var key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(entry, key))
        __defProp(entry, key, {
          get: __accessProp.bind(from, key),
          enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
        });
  }
  __moduleCache.set(from, entry);
  return entry;
};
var __moduleCache;
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
var __returnValue = (v) => v;
function __exportSetter(name, newValue) {
  this[name] = __returnValue.bind(null, newValue);
}
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, {
      get: all[name],
      enumerable: true,
      configurable: true,
      set: __exportSetter.bind(all, name)
    });
};
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
var __require = import.meta.require;

// ../mcp/src/manager.ts
import { Client } from "@modelcontextprotocol/sdk/client/index.js";

// ../mcp/src/logger.ts
class Logger {
  context;
  level = "info";
  handler = null;
  constructor(context, handler = null) {
    this.context = context;
    this.handler = handler;
  }
  setHandler(handler) {
    this.handler = handler;
  }
  log(level, message, data) {
    if (this.handler) {
      this.handler(level, this.context, message, data);
      return;
    }
  }
  debug(message, data) {
    this.log("debug", message, data);
  }
  info(message, data) {
    this.log("info", message, data);
  }
  warn(message, data) {
    this.log("warn", message, data);
  }
  error(message, data) {
    this.log("error", message, data);
  }
  child(context) {
    return new Logger(`${this.context}:${context}`, this.handler);
  }
  setLevel(level) {
    this.level = level;
  }
}
var logger = new Logger("mcp");

// ../mcp/src/manager.ts
import * as path from "path";

// ../mcp/src/transports/index.ts
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";

// ../mcp/src/transports/sse.ts
class SSETransport {
  baseUrl;
  messagesUrl = null;
  headers;
  abortController = null;
  cookies = [];
  startResolve = null;
  startReject = null;
  sessionId;
  onmessage;
  onerror;
  onclose;
  constructor(config) {
    this.baseUrl = config.url;
    this.headers = config.headers ?? {};
  }
  async start() {
    this.abortController = new AbortController;
    return new Promise(async (resolve, reject) => {
      const timeout = setTimeout(() => {
        this.startResolve = null;
        this.startReject = null;
        resolve();
      }, 5000);
      this.startResolve = () => {
        clearTimeout(timeout);
        this.startResolve = null;
        this.startReject = null;
        resolve();
      };
      this.startReject = (err) => {
        clearTimeout(timeout);
        this.startResolve = null;
        this.startReject = null;
        reject(err);
      };
      try {
        logger.debug(`[SSE] Connecting to: ${this.baseUrl}`);
        const response = await fetch(this.baseUrl, {
          method: "GET",
          headers: {
            Accept: "application/json, text/event-stream",
            "Cache-Control": "no-cache",
            ...this.headers
          },
          signal: this.abortController.signal
        });
        if (response.status === 405) {
          logger.debug(`[SSE] GET not allowed (405), falling back to Streamable HTTP pattern for ${this.baseUrl}`);
          this.startResolve();
          return;
        }
        if (!response.ok) {
          this.startReject(new Error(`MCP SSE connection failed: ${response.status} ${response.statusText}`));
          return;
        }
        this.readSessionId(response);
        if (response.body) {
          this.startReading(response.body);
        } else {
          this.startResolve();
        }
      } catch (error) {
        if (error.name !== "AbortError") {
          this.startReject(error);
        }
      }
    });
  }
  readSessionId(response) {
    const sessionId = response.headers.get("x-session-id") ?? response.headers.get("mcp-session-id");
    if (sessionId) {
      this.sessionId = sessionId;
    }
    const setCookie = response.headers.get("set-cookie");
    if (setCookie) {
      const newCookies = setCookie.split(",").map((c) => c.split(";")[0].trim());
      this.cookies = [...new Set([...this.cookies, ...newCookies])];
    }
  }
  startReading(stream) {
    const reader = stream.getReader();
    const decoder = new TextDecoder;
    let buffer = "";
    this.processStream(reader, decoder, buffer).catch((error) => {
      if (this.onerror && error.name !== "AbortError") {
        this.onerror(error instanceof Error ? error : new Error(String(error)));
      }
    });
  }
  async processStream(reader, decoder, buffer) {
    try {
      let eventType = "message";
      let eventData = "";
      while (true) {
        const { done, value } = await reader.read();
        if (done) {
          return;
        }
        buffer += decoder.decode(value, { stream: true });
        const lines = buffer.split(`
`);
        buffer = lines.pop() ?? "";
        for (const line of lines) {
          if (line.startsWith("event: ")) {
            eventType = line.slice(7).trim();
          } else if (line.startsWith("data: ")) {
            const data = line.slice(6);
            if (data.trim() === "[DONE]") {
              this.onclose?.();
              return;
            }
            eventData += data + `
`;
          } else if (line === "") {
            if (eventData) {
              eventData = eventData.trim();
              if (eventType === "endpoint") {
                try {
                  this.messagesUrl = new URL(eventData, this.baseUrl).href;
                  logger.debug(`[SSE] Messages endpoint received: ${this.messagesUrl}`);
                  this.startResolve?.();
                } catch (e) {
                  logger.warn(`[SSE] Failed to parse endpoint: ${eventData}`);
                }
              } else if (eventType === "message" || eventType === "") {
                try {
                  const parsed = JSON.parse(eventData);
                  this.onmessage?.(parsed);
                } catch {}
              }
              eventData = "";
            }
            eventType = "message";
          }
        }
      }
    } catch (error) {
      if (error.name !== "AbortError") {
        this.onerror?.(error instanceof Error ? error : new Error(String(error)));
      }
    }
  }
  async close() {
    this.abortController?.abort();
    this.abortController = null;
    this.sessionId = undefined;
    this.onclose?.();
  }
  async send(message) {
    if (!this.abortController) {
      throw new Error("SSE transport not started \u2014 llama start() primero");
    }
    const targetUrl = this.messagesUrl || this.baseUrl;
    let url = targetUrl;
    if (this.sessionId && !url.includes(`sessionId=${this.sessionId}`)) {
      url = `${targetUrl}${targetUrl.includes("?") ? "&" : "?"}sessionId=${this.sessionId}`;
    }
    const response = await fetch(url, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Accept: "application/json, text/event-stream",
        ...this.headers,
        ...this.cookies.length > 0 ? { Cookie: this.cookies.join("; ") } : {}
      },
      body: JSON.stringify(message),
      signal: this.abortController.signal
    });
    this.readSessionId(response);
    if (!response.ok) {
      const body = await response.text().catch(() => "");
      throw new Error(`MCP message failed (${response.status}): ${body || response.statusText}`);
    }
    const contentType = response.headers.get("content-type") ?? "";
    if (contentType.includes("text/event-stream") && response.body) {
      this.startReading(response.body);
    } else if (contentType.includes("application/json")) {
      const text = await response.text();
      if (text.trim()) {
        try {
          this.onmessage?.(JSON.parse(text));
        } catch {}
      }
    }
  }
}

// ../mcp/src/transports/websocket.ts
class WebSocketTransport {
  url;
  ws = null;
  headers;
  intentionallyClosed = false;
  reconnectAttempts = 0;
  reconnectDelay;
  reconnectMaxAttempts;
  shouldReconnect;
  onmessage;
  onerror;
  onclose;
  constructor(config) {
    this.url = config.url;
    this.headers = config.headers;
    this.shouldReconnect = config.reconnect ?? true;
    this.reconnectDelay = config.reconnectDelay ?? 3000;
    this.reconnectMaxAttempts = config.reconnectMaxAttempts ?? 10;
  }
  async start() {
    this.intentionallyClosed = false;
    this.reconnectAttempts = 0;
    return this.connect();
  }
  connect() {
    return new Promise((resolve, reject) => {
      const ws = this.headers && Object.keys(this.headers).length > 0 ? new WebSocket(this.url, {
        headers: this.headers
      }) : new WebSocket(this.url);
      this.ws = ws;
      let resolved = false;
      ws.onopen = () => {
        resolved = true;
        this.reconnectAttempts = 0;
        resolve();
      };
      ws.onmessage = (event) => {
        try {
          const data = JSON.parse(event.data);
          this.onmessage?.(data);
        } catch {}
      };
      ws.onerror = (event) => {
        const error = event.error ?? new Error(`WebSocket error en ${this.url}`);
        if (!resolved) {
          reject(error);
        } else {
          this.onerror?.(error instanceof Error ? error : new Error(String(error)));
        }
      };
      ws.onclose = (event) => {
        this.ws = null;
        if (this.intentionallyClosed) {
          this.onclose?.();
          return;
        }
        if (!resolved) {
          reject(new Error(`WebSocket cerrado antes de conectar \u2014 code: ${event.code}, reason: ${event.reason}`));
          return;
        }
        if (this.shouldReconnect && this.reconnectAttempts < this.reconnectMaxAttempts) {
          this.reconnectAttempts++;
          const delay = this.reconnectDelay * this.reconnectAttempts;
          setTimeout(async () => {
            try {
              await this.connect();
            } catch (err) {
              this.onerror?.(err instanceof Error ? err : new Error(String(err)));
              this.onclose?.();
            }
          }, delay);
        } else {
          this.onerror?.(new Error(`WebSocket desconectado despu\xE9s de ${this.reconnectAttempts} intentos \u2014 ${this.url}`));
          this.onclose?.();
        }
      };
    });
  }
  async close() {
    this.intentionallyClosed = true;
    if (this.ws) {
      this.ws.close(1000, "Client closed connection");
      this.ws = null;
    }
  }
  async send(message) {
    if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
      throw new Error(`WebSocket no est\xE1 conectado \u2014 readyState: ${this.ws?.readyState ?? "null"}`);
    }
    this.ws.send(JSON.stringify(message));
  }
  get isConnected() {
    return this.ws !== null && this.ws.readyState === WebSocket.OPEN;
  }
}

// ../mcp/src/transports/index.ts
function createTransport(options) {
  switch (options.type) {
    case "stdio": {
      if (!options.stdio) {
        throw new Error("stdio config required for stdio transport");
      }
      return new StdioClientTransport({
        command: options.stdio.command,
        args: options.stdio.args ?? [],
        env: options.stdio.env ?? process.env
      });
    }
    case "sse": {
      if (!options.sse) {
        throw new Error("sse config required for SSE transport");
      }
      return new SSETransport(options.sse);
    }
    case "websocket": {
      if (!options.websocket) {
        throw new Error("websocket config required for WebSocket transport");
      }
      return new WebSocketTransport(options.websocket);
    }
    default: {
      const _exhaustive = options.type;
      throw new Error(`Unknown transport type: ${_exhaustive}`);
    }
  }
}

// ../mcp/src/manager.ts
class MCPClientManager {
  servers = new Map;
  config;
  log = logger.child("mcp");
  constructor(config) {
    this.config = config;
  }
  setLogHandler(handler) {
    logger.setHandler(handler);
  }
  async initialize() {
    const servers = this.config.servers ?? {};
    for (const [name, serverConfig] of Object.entries(servers)) {
      if (serverConfig.enabled !== false) {
        this.servers.set(name, {
          name,
          config: serverConfig,
          client: null,
          transport: null,
          status: "disconnected",
          tools: [],
          resources: [],
          prompts: [],
          reconnectAttempts: 0
        });
      }
    }
    this.log.info(`MCP Client initialized with ${this.servers.size} servers`);
    await this.connectAll();
  }
  async updateConfig(config) {
    this.config = config;
    const newServers = this.config.servers ?? {};
    for (const name of this.servers.keys()) {
      if (!newServers[name] || newServers[name].enabled === false) {
        await this.disconnectServer(name);
        this.servers.delete(name);
      }
    }
    for (const [name, serverConfig] of Object.entries(newServers)) {
      if (serverConfig.enabled !== false) {
        const existing = this.servers.get(name);
        if (existing) {
          const configChanged = JSON.stringify(existing.config) !== JSON.stringify(serverConfig);
          if (configChanged) {
            const wasConnected = existing.status === "connected";
            await this.disconnectServer(name);
            existing.config = serverConfig;
            if (wasConnected) {
              await this.connectServer(name).catch((err) => {
                this.log.error(`Failed to reconnect ${name} after config update: ${err.message}`);
              });
            }
          }
        } else {
          this.servers.set(name, {
            name,
            config: serverConfig,
            client: null,
            transport: null,
            status: "disconnected",
            tools: [],
            resources: [],
            prompts: [],
            reconnectAttempts: 0
          });
          await this.connectServer(name).catch((err) => {
            this.log.error(`Failed to connect new server ${name}: ${err.message}`);
          });
        }
      }
    }
  }
  expandPath(p) {
    if (p.startsWith("~")) {
      return path.join(process.env.HOME ?? "", p.slice(1));
    }
    return p;
  }
  createTransportForServer(state) {
    const transportType = state.config.transport;
    switch (transportType) {
      case "stdio": {
        const command = state.config.command ?? "npx";
        const args = state.config.args ?? [];
        const env = {};
        for (const [key, value] of Object.entries(process.env)) {
          if (value !== undefined)
            env[key] = value;
        }
        if (state.config.env) {
          for (const [key, value] of Object.entries(state.config.env)) {
            env[key] = this.expandPath(value);
          }
        }
        return createTransport({ type: "stdio", stdio: { command, args, env } });
      }
      case "sse": {
        const url = state.config.url;
        if (!url)
          throw new Error("SSE transport requires 'url' config");
        return createTransport({
          type: "sse",
          sse: { url, headers: state.config.headers }
        });
      }
      case "websocket": {
        const url = state.config.url;
        if (!url)
          throw new Error("WebSocket transport requires 'url' config");
        return createTransport({
          type: "websocket",
          websocket: { url, headers: state.config.headers }
        });
      }
      default:
        throw new Error(`Unknown transport type: ${transportType}`);
    }
  }
  async connectServer(name) {
    const state = this.servers.get(name);
    if (!state)
      throw new Error(`MCP server not found: ${name}`);
    if (state.status === "connected")
      return;
    state.status = "connecting";
    state.lastError = undefined;
    this.log.info(`Connecting to MCP server: ${name}`);
    try {
      const transport = this.createTransportForServer(state);
      const client = new Client({ name: "hive", version: "0.1.0" }, { capabilities: {} });
      await client.connect(transport);
      state.client = client;
      state.transport = transport;
      state.status = "connected";
      state.reconnectAttempts = 0;
      await this.discoverCapabilities(name);
      this.log.info(`Connected to MCP server: ${name}`, {
        tools: state.tools.length,
        resources: state.resources.length,
        prompts: state.prompts.length
      });
    } catch (error) {
      state.status = "error";
      state.lastError = error.message;
      this.log.error(`Failed to connect to MCP server ${name}: ${state.lastError}`);
      throw error;
    }
  }
  async discoverCapabilities(name) {
    const state = this.servers.get(name);
    if (!state?.client)
      return;
    try {
      const toolsResult = await state.client.listTools();
      state.tools = (toolsResult.tools ?? []).map((t) => ({
        name: t.name,
        description: t.description ?? "",
        inputSchema: t.inputSchema
      }));
    } catch {
      this.log.debug(`No tools from MCP server: ${name}`);
    }
    try {
      const resourcesResult = await state.client.listResources();
      state.resources = (resourcesResult.resources ?? []).map((r) => ({
        uri: r.uri,
        name: r.name,
        description: r.description,
        mimeType: r.mimeType
      }));
    } catch {
      this.log.debug(`No resources from MCP server: ${name}`);
    }
    try {
      const promptsResult = await state.client.listPrompts();
      state.prompts = (promptsResult.prompts ?? []).map((p) => ({
        name: p.name,
        description: p.description,
        arguments: p.arguments
      }));
    } catch {
      this.log.debug(`No prompts from MCP server: ${name}`);
    }
  }
  async disconnectServer(name) {
    const state = this.servers.get(name);
    if (!state)
      return;
    if (state.client) {
      try {
        await state.client.close();
      } catch {}
    }
    state.client = null;
    state.transport = null;
    state.status = "disconnected";
    state.lastError = undefined;
    this.log.info(`Disconnected from MCP server: ${name}`);
  }
  async callTool(serverName, toolName, args) {
    const state = this.servers.get(serverName);
    if (!state?.client) {
      throw new Error(`MCP server not connected: ${serverName}`);
    }
    this.log.debug(`Calling MCP tool: ${serverName}/${toolName}`, { args });
    const result = await state.client.callTool({
      name: toolName,
      arguments: args
    });
    return result.content;
  }
  async readResource(serverName, uri) {
    const state = this.servers.get(serverName);
    if (!state?.client) {
      throw new Error(`MCP server not connected: ${serverName}`);
    }
    const result = await state.client.readResource({ uri });
    return result.contents;
  }
  getServerStatus(name) {
    return this.servers.get(name)?.status;
  }
  getServerTools(name) {
    return this.servers.get(name)?.tools ?? [];
  }
  getServerResources(name) {
    return this.servers.get(name)?.resources ?? [];
  }
  getAllTools() {
    const result = new Map;
    for (const [name, state] of this.servers) {
      if (state.status === "connected") {
        result.set(name, state.tools);
      }
    }
    return result;
  }
  listServers() {
    return Array.from(this.servers.values()).map((s) => ({
      name: s.name,
      status: s.status,
      tools: s.tools,
      resources: s.resources,
      prompts: s.prompts,
      url: s.config.transport === "stdio" ? `${s.config.command} ${s.config.args?.join(" ")}` : s.config.url,
      error: s.lastError
    }));
  }
  getServerDetails(name) {
    const s = this.servers.get(name);
    if (!s)
      return;
    const safeConfig = {
      ...s.config,
      headers: s.config.headers ? Object.fromEntries(Object.entries(s.config.headers).map(([k, v]) => [
        k,
        k.toLowerCase().includes("auth") || k.toLowerCase().includes("token") || k.toLowerCase().includes("key") ? `${v.slice(0, 4)}\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022` : v
      ])) : undefined
    };
    return {
      name: s.name,
      status: s.status,
      tools: s.tools,
      resources: s.resources,
      prompts: s.prompts,
      config: safeConfig,
      error: s.lastError
    };
  }
  async connectAll() {
    const promises = [];
    for (const name of this.servers.keys()) {
      promises.push(this.connectServer(name).catch((error) => {
        this.log.error(`Failed to connect ${name}: ${error.message}`);
      }));
    }
    await Promise.allSettled(promises);
  }
  async reconnectAll() {
    await this.disconnectAll();
    await this.connectAll();
  }
  async disconnectAll() {
    const promises = [];
    for (const name of this.servers.keys()) {
      promises.push(this.disconnectServer(name));
    }
    await Promise.allSettled(promises);
  }
}
export {
  logger,
  MCPClientManager
};
