// Standalone MCP client for Zo.
// Reads ZO_CLIENT_IDENTITY_TOKEN from env, talks JSON-RPC to api.zo.computer/mcp.

const MCP_URL = "https://api.zo.computer/mcp";

export interface MCPTool {
  name: string;
  description?: string;
  input_schema?: {
    type: string;
    properties?: Record<string, any>;
    required?: string[];
  };
}

interface McpResponse {
  result?: {
    content?: { type: string; text?: string }[];
    tools?: MCPTool[];
    isError?: boolean;
  };
  error?: { code: number; message: string };
}

function getToken(): string {
  const t = process.env.ZO_CLIENT_IDENTITY_TOKEN;
  if (!t) throw new Error("ZO_CLIENT_IDENTITY_TOKEN not set");
  return t;
}

async function mcpCall(method: string, params?: any): Promise<McpResponse> {
  const res = await fetch(MCP_URL, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${getToken()}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ jsonrpc: "2.0", id: 1, method, params }),
  });
  return res.json();
}

export async function listTools(): Promise<MCPTool[]> {
  const data = await mcpCall("tools/list");
  return data.result?.tools ?? [];
}

export async function callTool(name: string, args: any): Promise<string> {
  const data = await mcpCall("tools/call", { name, arguments: args });
  if (data.error) throw new Error(`MCP error ${data.error.code}: ${data.error.message}`);
  const content = data.result?.content ?? [];
  const text = content.map((c: any) => c.text ?? "").join("\n").trim();
  if (data.result?.isError) throw new Error(text || "Tool returned error");
  return text;
}
