import { spawn } from "node:child_process";
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
class McpClient {
  constructor(client, transport, apiKeySecret, childProcess) {
    this.client = client;
    this.transport = transport;
    this.apiKeySecret = apiKeySecret;
    this.childProcess = childProcess;
  }
  /**
   * Connect to an MCP server via the specified transport.
   */
  static async connect(options) {
    if (options.transport === "stdio") {
      return McpClient.connectStdio(options);
    } else {
      return McpClient.connectHttp(options);
    }
  }
  /**
   * Connect via stdio transport (spawn subprocess).
   */
  static async connectStdio(options) {
    const command = options.command ?? "yarn";
    const args = options.args ?? [
      "mercato",
      "ai_assistant",
      "mcp:serve",
      "--api-key",
      options.apiKeySecret
    ];
    const cwd = options.cwd ?? process.cwd();
    const childProcess = spawn(command, args, {
      cwd,
      stdio: ["pipe", "pipe", "pipe"],
      env: { ...process.env }
    });
    childProcess.stderr?.on("data", (data) => {
      const message = data.toString().trim();
      if (message) {
        console.error(`[MCP Client] ${message}`);
      }
    });
    const transport = new StdioClientTransport({
      command,
      args,
      cwd,
      env: process.env
    });
    const client = new Client(
      { name: "open-mercato-client", version: "0.1.0" },
      { capabilities: {} }
    );
    await client.connect(transport);
    return new McpClient(client, transport, options.apiKeySecret, childProcess);
  }
  /**
   * Connect via HTTP transport.
   */
  static async connectHttp(options) {
    const transport = new StreamableHTTPClientTransport(
      new URL(options.url),
      {
        requestInit: {
          headers: {
            "x-api-key": options.apiKeySecret
          }
        }
      }
    );
    const client = new Client(
      { name: "open-mercato-client", version: "0.1.0" },
      { capabilities: {} }
    );
    await client.connect(transport);
    return new McpClient(client, transport, options.apiKeySecret);
  }
  /**
   * List available tools from the server.
   */
  async listTools() {
    const response = await this.client.listTools();
    return response.tools.map((tool) => ({
      name: tool.name,
      description: tool.description ?? "",
      inputSchema: tool.inputSchema ?? {}
    }));
  }
  /**
   * Call a tool on the server.
   */
  async callTool(name, args) {
    try {
      const response = await this.client.callTool({
        name,
        arguments: args
      });
      const content = response.content;
      if (!Array.isArray(content) || content.length === 0) {
        return { success: true, result: null };
      }
      const firstContent = content[0];
      if (firstContent.type === "text") {
        try {
          const parsed = JSON.parse(firstContent.text);
          if (response.isError || parsed.error) {
            return {
              success: false,
              error: parsed.error ?? "Unknown error"
            };
          }
          return { success: true, result: parsed };
        } catch {
          return { success: true, result: firstContent.text };
        }
      }
      return { success: true, result: content };
    } catch (error) {
      const message = error instanceof Error ? error.message : String(error);
      return { success: false, error: message };
    }
  }
  /**
   * Close the client and release resources.
   */
  async close() {
    try {
      await this.client.close();
    } catch {
    }
    try {
      await this.transport.close();
    } catch {
    }
    if (this.childProcess) {
      this.childProcess.kill();
      this.childProcess = void 0;
    }
  }
}
export {
  McpClient
};
//# sourceMappingURL=mcp-client.js.map
