import {
  IntegrationError,
  createCatalogExecutorProvider,
  importMcpConnector
} from "./chunk-5QU3YCGR.js";
import "./chunk-TC5OMANJ.js";
import "./chunk-IKCXDQVP.js";
import "./chunk-H4XYLS7T.js";
import "./chunk-FAFQZJPZ.js";
import "./chunk-IA5GCKM6.js";
import "./chunk-7P2LN4VT.js";
import "./chunk-376UBTNB.js";
import "./chunk-JXXPAUCX.js";
import "./chunk-2TW2QKGZ.js";
import "./chunk-OMLQCESJ.js";
import "./chunk-PZ5AY32C.js";

// src/mcp.ts
var MCP_PROTOCOL_VERSION = "2025-06-18";
var McpHttpClient = class {
  constructor(config) {
    this.config = config;
  }
  config;
  nextId = 1;
  sessionId;
  negotiatedVersion;
  initializing;
  get fetchImpl() {
    return this.config.fetchImpl ?? fetch;
  }
  async post(body) {
    const headers = {
      "Content-Type": "application/json",
      Accept: "application/json, text/event-stream",
      ...this.config.headers ?? {}
    };
    const version = this.negotiatedVersion ?? this.config.protocolVersion ?? MCP_PROTOCOL_VERSION;
    headers["MCP-Protocol-Version"] = version;
    if (this.sessionId) headers["Mcp-Session-Id"] = this.sessionId;
    let response;
    try {
      response = await this.fetchImpl(this.config.url, {
        method: "POST",
        headers,
        body: JSON.stringify(body)
      });
    } catch (error) {
      throw new IntegrationError(
        `MCP server unreachable: ${error instanceof Error ? error.message : String(error)}`,
        "provider_failure"
      );
    }
    const session = response.headers.get("mcp-session-id");
    if (session) this.sessionId = session;
    if (!response.ok) {
      throw new IntegrationError(`MCP server returned HTTP ${response.status}`, "provider_failure");
    }
    if (body.id === void 0) return void 0;
    const contentType = response.headers.get("content-type") ?? "";
    const text = await response.text();
    const message = contentType.includes("text/event-stream") ? findSseResponse(text, body.id) : JSON.parse(text);
    if (!message) {
      throw new IntegrationError("MCP server response missing a result for the request", "provider_failure");
    }
    if (message.error) {
      throw new IntegrationError(`MCP error ${message.error.code}: ${message.error.message}`, "provider_failure");
    }
    return message;
  }
  async request(method, params) {
    const response = await this.post({ jsonrpc: "2.0", id: this.nextId++, method, ...params ? { params } : {} });
    return response?.result;
  }
  /** Idempotent handshake; concurrent callers share one in-flight init. */
  async initialize() {
    if (this.negotiatedVersion) return;
    this.initializing ??= (async () => {
      const result = await this.request("initialize", {
        protocolVersion: this.config.protocolVersion ?? MCP_PROTOCOL_VERSION,
        capabilities: {},
        clientInfo: this.config.clientInfo ?? { name: "tangle-agent-integrations", version: "1" }
      });
      this.negotiatedVersion = result?.protocolVersion ?? this.config.protocolVersion ?? MCP_PROTOCOL_VERSION;
      await this.post({ jsonrpc: "2.0", method: "notifications/initialized" });
    })().catch((error) => {
      this.initializing = void 0;
      throw error;
    });
    await this.initializing;
  }
  /** Full tool catalog, following `nextCursor` pagination. */
  async listTools() {
    await this.initialize();
    const tools = [];
    let cursor;
    do {
      const result = await this.request("tools/list", cursor ? { cursor } : {});
      tools.push(...result?.tools ?? []);
      cursor = result?.nextCursor;
    } while (cursor);
    return tools;
  }
  async callTool(name, args) {
    await this.initialize();
    const result = await this.request("tools/call", { name, arguments: args ?? {} });
    return {
      content: result?.content ?? [],
      isError: result?.isError === true,
      structured: result?.structuredContent
    };
  }
};
async function discoverMcpConnector(client, options) {
  const tools = await client.listTools();
  return importMcpConnector(
    { tools },
    {
      providerId: options.id,
      connectorId: options.connectorId,
      connectorTitle: options.connectorTitle,
      category: options.category,
      auth: "custom",
      scopes: options.scopes,
      dataClass: options.dataClass,
      defaultRisk: options.defaultRisk ?? "write"
    }
  );
}
async function createMcpProvider(options) {
  const client = new McpHttpClient(options.server);
  const connector = await discoverMcpConnector(client, options);
  return createCatalogExecutorProvider({
    id: options.id,
    kind: "mcp",
    connectors: [connector],
    async executeAction({ request, action }) {
      const result = await client.callTool(action.id, request.input);
      return {
        ok: !result.isError,
        action: action.id,
        output: result.structured ?? result.content,
        metadata: { mcp: true, ...result.isError ? { isError: true } : {} }
      };
    }
  });
}
function findSseResponse(body, id) {
  for (const event of body.split(/\n\n/)) {
    const data = event.split("\n").filter((line) => line.startsWith("data:")).map((line) => line.slice(5).trim()).join("");
    if (!data) continue;
    try {
      const parsed = JSON.parse(data);
      if (parsed.id === id) return parsed;
    } catch {
    }
  }
  return void 0;
}
export {
  MCP_PROTOCOL_VERSION,
  McpHttpClient,
  createMcpProvider,
  discoverMcpConnector
};
//# sourceMappingURL=mcp.js.map