import {
  LangWatchApiError,
  makeRequest
} from "./chunk-CAY57CKF.js";
import {
  requireApiKey
} from "./chunk-KOO5733S.js";

// src/create-mcp-server.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z as z2 } from "zod";

// package.json
var package_default = {
  name: "@langwatch/mcp-server",
  version: "0.10.1",
  description: "An MCP server for Langwatch.",
  type: "module",
  main: "./dist/index.js",
  module: "./dist/index.js",
  types: "./dist/index.d.ts",
  exports: {
    ".": {
      import: "./dist/index.js",
      require: "./dist/index.js"
    },
    "./create-mcp-server": {
      types: "./src/create-mcp-server.d.ts",
      import: "./dist/create-mcp-server.js",
      require: "./dist/create-mcp-server.js",
      default: "./dist/create-mcp-server.js"
    },
    "./config": {
      types: "./src/config.d.ts",
      import: "./dist/config.js",
      require: "./dist/config.js",
      default: "./dist/config.js"
    }
  },
  repository: {
    type: "git",
    url: "https://github.com/langwatch/langwatch.git",
    directory: "mcp-server"
  },
  scripts: {
    start: "tsx src/index.ts",
    build: "tsup && node build.js",
    prepublish: "pnpm run build",
    test: "vitest"
  },
  author: "",
  license: "MIT",
  engines: {
    node: ">=18.0.0"
  },
  devDependencies: {
    "@ai-sdk/anthropic": "^3.0.44",
    "@anthropic-ai/claude-code": "^2.1.119",
    "@eslint/js": "^10.0.1",
    "@langwatch/scenario": "^0.4.6",
    "@types/debug": "^4.1.12",
    "@types/eslint__js": "^8.42.3",
    "@types/express": "^5.0.6",
    "@types/node": "^25.6.0",
    "@types/yargs": "^17.0.33",
    "@typescript/native-preview": "7.0.0-dev.20250911.1",
    ai: "^6.0.161",
    dotenv: "^17.2.2",
    esbuild: "^0.25.0",
    eslint: "^10.2.1",
    tsup: "^8.1.0",
    tsx: "^4.20.5",
    typescript: "^5.0.0",
    "typescript-eslint": "^8.55.0"
  },
  dependencies: {
    "@modelcontextprotocol/sdk": "^1.26.0",
    "@opentelemetry/context-async-hooks": "^2.1.0",
    "@opentelemetry/sdk-node": "^0.217.0",
    chalk: "^5.6.2",
    "date-fns": "^4.1.0",
    express: "^5.2.1",
    "node-pty": "^1.0.0",
    vitest: "^3.2.4",
    yargs: "^17.7.2",
    zod: "^4.3.6",
    "zod-validation-error": "^5.0.0"
  },
  bin: {
    "langwatch-mcp-server": "./dist/index.js"
  }
};

// src/schemas/create-dataset.ts
import { z } from "zod";
var DATASET_COLUMN_TYPES = [
  "string",
  "boolean",
  "number",
  "date",
  "list",
  "json",
  "spans",
  "rag_contexts",
  "chat_messages",
  "annotations",
  "evaluations",
  "image"
];
var datasetColumnTypeSchema = z.enum(DATASET_COLUMN_TYPES);
var datasetColumnDefinitionSchema = z.object({
  name: z.string().describe("Column name"),
  type: datasetColumnTypeSchema.describe("Column type")
});
var createDatasetSchema = z.object({
  name: z.string().min(1).describe("Dataset name"),
  columnTypes: z.array(datasetColumnDefinitionSchema).optional().describe("Column definitions for the dataset")
});

// src/tools/experiment-run-status.ts
var INTERRUPTED_THRESHOLD_MS = 5 * 60 * 1e3;
var deriveRunStatus = (timestamps, now = Date.now()) => {
  if (timestamps.stoppedAt != null) return "stopped";
  if (timestamps.finishedAt != null) return "completed";
  if (timestamps.updatedAt != null && now - timestamps.updatedAt > INTERRUPTED_THRESHOLD_MS) {
    return "interrupted";
  }
  return "running";
};
var isTerminalStatus = (status) => status === "completed" || status === "stopped";

// src/tools/get-experiment-results.ts
var DEFAULT_ROW_CAP = 50;
var rowKey = (index, targetId) => `${index}:${targetId ?? ""}`;
var summarizeEntry = (entry) => {
  const candidates = ["input", "question", "query", "prompt", "user"];
  for (const key of candidates) {
    const value = entry[key];
    if (typeof value === "string" && value.length > 0) {
      return value.length > 80 ? `${value.slice(0, 77)}...` : value;
    }
  }
  return "";
};
var isFailedEvaluation = (e) => e.status === "error" || e.passed === false;
var isFailedRow = ({
  entry,
  evaluations
}) => Boolean(entry.error) || evaluations.some(isFailedEvaluation);
async function handleExperimentResults(params) {
  const filter = params.filter ?? "all";
  const evaluatorFilter = params.evaluator?.trim();
  const limit = typeof params.limit === "number" && params.limit > 0 ? Math.min(params.limit, DEFAULT_ROW_CAP) : DEFAULT_ROW_CAP;
  const search = new URLSearchParams();
  if (params.experimentSlug) search.set("experimentSlug", params.experimentSlug);
  const qs = search.toString() ? `?${search.toString()}` : "";
  let results;
  try {
    results = await makeRequest(
      "GET",
      `/api/experiments/runs/${encodeURIComponent(params.runId)}/results${qs}`
    );
  } catch (error) {
    const message = error instanceof Error ? error.message : String(error);
    const status = error instanceof LangWatchApiError ? error.status : error && typeof error === "object" && "status" in error && typeof error.status === "number" ? error.status : void 0;
    if (status === 404 || status === void 0 && /404|not found/i.test(message)) {
      return [
        `# Evaluation Results: ${params.runId}`,
        "",
        "**Status**: not found",
        "",
        `Could not load results for run \`${params.runId}\`. The run id may be incorrect, or its run state may have expired (Redis keeps it for 24h).`,
        "",
        "> Pass `experimentSlug` to load results for runs older than 24h. Discover the slug with `platform_experiment_list`, then `platform_experiment_list_runs` for the run ids."
      ].join("\n");
    }
    throw error;
  }
  if (!results) {
    return [
      `# Evaluation Results: ${params.runId}`,
      "",
      "**Status**: not found",
      "",
      `Could not load results for run \`${params.runId}\`.`,
      "",
      "> Pass `experimentSlug` if the run is older than 24h. Discover the slug with `platform_experiment_list`, then `platform_experiment_list_runs` to confirm the run id."
    ].join("\n");
  }
  const runStatus2 = deriveRunStatus(results.timestamps);
  const partial = !isTerminalStatus(runStatus2);
  const evaluationsByRow = /* @__PURE__ */ new Map();
  for (const evaluation of results.evaluations) {
    if (evaluatorFilter && evaluation.evaluator !== evaluatorFilter) continue;
    const key = rowKey(evaluation.index, evaluation.targetId);
    const list = evaluationsByRow.get(key) ?? [];
    list.push(evaluation);
    evaluationsByRow.set(key, list);
  }
  const evaluatorNames = Array.from(
    new Set(
      (evaluatorFilter ? results.evaluations.filter((e) => e.evaluator === evaluatorFilter) : results.evaluations).map((e) => e.evaluator)
    )
  );
  let rows = results.dataset.map((entry) => ({
    entry,
    evaluations: evaluationsByRow.get(rowKey(entry.index, entry.targetId)) ?? []
  }));
  if (filter === "failed") {
    rows = rows.filter(
      (r) => isFailedRow({ entry: r.entry, evaluations: r.evaluations })
    );
  }
  const totalMatching = rows.length;
  const rowsForSummary = rows;
  const truncated = rows.length > limit;
  rows = rows.slice(0, limit);
  const evaluatorAverages = /* @__PURE__ */ new Map();
  for (const r of rowsForSummary) {
    for (const e of r.evaluations) {
      const stats = evaluatorAverages.get(e.evaluator) ?? {
        sum: 0,
        count: 0,
        passed: 0,
        failed: 0,
        errored: 0
      };
      if (typeof e.score === "number") {
        stats.sum += e.score;
        stats.count += 1;
      }
      if (e.status === "error") stats.errored += 1;
      else if (e.passed === true) stats.passed += 1;
      else if (e.passed === false) stats.failed += 1;
      evaluatorAverages.set(e.evaluator, stats);
    }
  }
  const lines = [];
  lines.push(`# Evaluation Results: ${results.runId}`);
  lines.push("");
  lines.push(`**Experiment**: ${results.experimentId}`);
  lines.push(`**Status**: ${runStatus2}`);
  if (typeof results.total === "number" && results.total > 0) {
    lines.push(
      `**Progress**: ${results.progress ?? results.dataset.length}/${results.total} rows`
    );
  }
  lines.push(`**Total rows**: ${results.dataset.length}`);
  lines.push(`**Total evaluations**: ${results.evaluations.length}`);
  if (filter === "failed") {
    lines.push(`**Filter**: failed only`);
  }
  if (evaluatorFilter) {
    lines.push(`**Evaluator filter**: ${evaluatorFilter}`);
  }
  if (partial) {
    lines.push("");
    lines.push(
      runStatus2 === "interrupted" ? "> These are partial results. The run never sent a finished/stopped marker and has had no updates recently, so it likely was interrupted before completing. The rows below are everything recorded so far." : "> These are partial results. The run is still in progress, so more rows may appear on a later call."
    );
  }
  lines.push("");
  if (evaluatorAverages.size > 0) {
    lines.push("## Evaluator Summary");
    lines.push("");
    lines.push("| Evaluator | Avg Score | Passed | Failed | Errored |");
    lines.push("| --- | --- | --- | --- | --- |");
    for (const [name, stats] of evaluatorAverages) {
      const avg = stats.count > 0 ? (stats.sum / stats.count).toFixed(3) : "\u2014";
      lines.push(
        `| ${name} | ${avg} | ${stats.passed} | ${stats.failed} | ${stats.errored} |`
      );
    }
    lines.push("");
  }
  if (rows.length === 0) {
    if (filter === "failed") {
      lines.push("_No rows matched the filter._");
    } else if (runStatus2 === "running") {
      lines.push(
        "_No rows recorded yet. The run is still in progress; call again shortly._"
      );
    } else if (runStatus2 === "interrupted") {
      lines.push("_No rows were recorded before the run was interrupted._");
    } else {
      lines.push("_No rows recorded for this run._");
    }
    return lines.join("\n");
  }
  lines.push(
    `## Rows (${rows.length}${truncated ? ` of ${totalMatching}` : ""})`
  );
  lines.push("");
  for (const { entry, evaluations } of rows) {
    const summary = summarizeEntry(entry.entry);
    lines.push(`### Row #${entry.index}${summary ? ` \u2014 ${summary}` : ""}`);
    if (entry.error) {
      lines.push(`- **Error**: ${entry.error}`);
    }
    if (entry.traceId) {
      lines.push(`- **Trace ID**: \`${entry.traceId}\``);
    }
    if (evaluations.length === 0) {
      lines.push(
        evaluatorNames.length === 0 ? "- _No evaluations recorded_" : "- _No evaluations recorded for this row_"
      );
    }
    for (const e of evaluations) {
      const parts = [`**${e.evaluator}**`];
      if (e.status === "error") parts.push("status=error");
      else if (typeof e.score === "number") parts.push(`score=${e.score.toFixed(3)}`);
      if (typeof e.passed === "boolean") {
        parts.push(`passed=${e.passed ? "yes" : "no"}`);
      }
      if (e.label) parts.push(`label=${e.label}`);
      lines.push(`- ${parts.join(" \xB7 ")}`);
      if (e.details) {
        lines.push(`  - details: ${e.details}`);
      }
    }
    lines.push("");
  }
  if (truncated) {
    lines.push(
      `> Output truncated to ${limit} rows of ${totalMatching} matching to protect the agent's context window. Pass \`limit\` to expand or filter further.`
    );
  }
  return lines.join("\n");
}

// src/tools/list-experiment-runs.ts
var DEFAULT_LIMIT = 25;
var MAX_LIMIT = 100;
var formatEpoch = (epoch) => {
  if (!epoch || !Number.isFinite(epoch)) return "\u2014";
  return new Date(epoch).toISOString().replace("T", " ").slice(0, 19) + " UTC";
};
var passRate = (evaluations) => {
  const entries = Object.values(evaluations ?? {});
  if (entries.length === 0) return "\u2014";
  const passed = entries.filter((e) => typeof e.averagePassed === "number");
  if (passed.length === 0) {
    const scored = entries.filter((e) => typeof e.averageScore === "number");
    if (scored.length === 0) return "\u2014";
    const avg2 = scored.reduce((sum, e) => sum + (e.averageScore ?? 0), 0) / scored.length;
    return `${avg2.toFixed(2)} avg`;
  }
  const avg = passed.reduce((sum, e) => sum + (e.averagePassed ?? 0), 0) / passed.length;
  return `${(avg * 100).toFixed(0)}% pass`;
};
var runStatus = (run) => {
  if (run.timestamps.stoppedAt) return "stopped";
  if (run.timestamps.finishedAt) return "completed";
  return "running";
};
async function handleExperimentListRuns(params) {
  const requested = typeof params.limit === "number" && params.limit > 0 ? params.limit : DEFAULT_LIMIT;
  const effectiveLimit = Math.min(requested, MAX_LIMIT);
  const search = new URLSearchParams();
  search.set("experimentSlug", params.experimentSlug);
  search.set("pageSize", String(effectiveLimit));
  let result;
  try {
    result = await makeRequest(
      "GET",
      `/api/experiments/runs?${search.toString()}`
    );
  } catch (error) {
    const message = error instanceof Error ? error.message : String(error);
    if (/404|not found/i.test(message)) {
      return [
        `# Evaluation Runs: ${params.experimentSlug}`,
        "",
        "**Status**: experiment not found",
        "",
        `No experiment with slug \`${params.experimentSlug}\` exists in this project.`,
        "",
        "> Run `platform_experiment_list` to discover available experiment slugs."
      ].join("\n");
    }
    throw error;
  }
  if (result.runs.length === 0) {
    return [
      `# Evaluation Runs: ${result.experimentSlug}`,
      "",
      "_This experiment has no runs yet._",
      "",
      `> Trigger a run with \`platform_run_experiment\` (slug: \`${result.experimentSlug}\`) to populate this list.`
    ].join("\n");
  }
  const lines = [];
  lines.push(`# Evaluation Runs: ${result.experimentSlug}`);
  lines.push("");
  lines.push(
    `Showing ${result.runs.length} of ${result.pagination.totalHits} run${result.pagination.totalHits === 1 ? "" : "s"}.`
  );
  if (result.pagination.hasMore) {
    lines.push(
      `> More runs exist beyond this limit. Re-run with a higher \`limit\` (max ${MAX_LIMIT}) if needed.`
    );
  }
  lines.push("");
  lines.push("| Run ID | Status | Started | Finished | Result |");
  lines.push("|--------|--------|---------|----------|--------|");
  for (const run of result.runs) {
    lines.push(
      `| \`${run.runId}\` | ${runStatus(run)} | ${formatEpoch(run.timestamps.createdAt)} | ${formatEpoch(run.timestamps.finishedAt ?? null)} | ${passRate(run.summary?.evaluations ?? {})} |`
    );
  }
  lines.push("");
  lines.push(
    "> Use `platform_experiment_status <runId>` for live progress, or `platform_experiment_results <runId>` for per-row results."
  );
  return lines.join("\n");
}

// src/tools/list-experiments.ts
var DEFAULT_LIMIT2 = 25;
var MAX_LIMIT2 = 100;
var formatTimestamp = (iso) => {
  if (!iso) return "\u2014";
  const d = new Date(iso);
  if (Number.isNaN(d.getTime())) return iso;
  return d.toISOString().replace("T", " ").slice(0, 19) + " UTC";
};
var escapeMarkdownTableCell = (value) => value.replace(/[\\|]/g, (c) => `\\${c}`).replace(/\n/g, " ");
var formatInlineCode = (value) => `\`${value.replace(/[\\`|]/g, (c) => `\\${c}`).replace(/\n/g, " ")}\``;
async function handleExperimentList(params) {
  const requested = typeof params.limit === "number" && params.limit > 0 ? params.limit : DEFAULT_LIMIT2;
  const effectiveLimit = Math.min(requested, MAX_LIMIT2);
  const search = new URLSearchParams();
  search.set("pageSize", String(effectiveLimit));
  const result = await makeRequest(
    "GET",
    `/api/experiments?${search.toString()}`
  );
  if (result.experiments.length === 0) {
    return [
      "# Experiments",
      "",
      "_No experiments found in this project._",
      "",
      "> Create an experiment in the LangWatch dashboard, then re-run this tool to discover its slug."
    ].join("\n");
  }
  const lines = [];
  lines.push("# Experiments");
  lines.push("");
  lines.push(
    `Showing ${result.experiments.length} of ${result.pagination.totalHits} experiment${result.pagination.totalHits === 1 ? "" : "s"}.`
  );
  if (result.pagination.hasMore) {
    lines.push(
      `> More experiments exist beyond this limit. Re-run with a higher \`limit\` (max ${MAX_LIMIT2}) if needed.`
    );
  }
  lines.push("");
  lines.push("| Slug | Name | Runs | Last Run |");
  lines.push("|------|------|------|----------|");
  for (const exp of result.experiments) {
    const name = escapeMarkdownTableCell(exp.name ?? exp.slug);
    lines.push(
      `| ${formatInlineCode(exp.slug)} | ${name} | ${exp.runsCount} | ${formatTimestamp(exp.lastRunAt)} |`
    );
  }
  lines.push("");
  lines.push(
    "> Use `platform_experiment_list_runs` with one of these slugs to see its runs."
  );
  return lines.join("\n");
}

// src/tools/run-experiment.ts
async function handleRunExperiment(params) {
  const result = await makeRequest(
    "POST",
    `/api/experiments/${encodeURIComponent(params.slug)}/run`
  );
  const lines = [];
  lines.push(`Evaluation started!
`);
  lines.push(`**Run ID**: ${result.runId}`);
  lines.push(`**Status**: ${result.status}`);
  lines.push(`**Total cells**: ${result.total}`);
  if (result.runUrl) lines.push(`**View at**: ${result.runUrl}`);
  lines.push("");
  lines.push(
    `> Use \`platform_experiment_status\` with run ID "${result.runId}" to check progress.`
  );
  return lines.join("\n");
}
async function statusFromResults(params) {
  const search = new URLSearchParams();
  if (params.experimentSlug) search.set("experimentSlug", params.experimentSlug);
  const qs = search.toString() ? `?${search.toString()}` : "";
  let results;
  try {
    results = await makeRequest(
      "GET",
      `/api/experiments/runs/${encodeURIComponent(params.runId)}/results${qs}`
    );
  } catch (error) {
    const code = error instanceof LangWatchApiError ? error.status : void 0;
    const message = error instanceof Error ? error.message : String(error);
    if (code === 404 || code === void 0 && /404|not found/i.test(message)) {
      return null;
    }
    throw error;
  }
  const status = deriveRunStatus(results.timestamps);
  const total = results.total ?? results.dataset?.length ?? 0;
  const progress = results.progress ?? results.dataset?.length ?? 0;
  const lines = [];
  lines.push(`# Evaluation Run ${params.runId}
`);
  lines.push(`**Status**: ${status}`);
  lines.push(`**Progress**: ${progress}/${total} cells`);
  if (results.timestamps.createdAt) {
    lines.push(
      `**Started**: ${new Date(results.timestamps.createdAt).toISOString()}`
    );
  }
  if (results.timestamps.finishedAt) {
    lines.push(
      `**Finished**: ${new Date(results.timestamps.finishedAt).toISOString()}`
    );
  }
  if (results.timestamps.stoppedAt) {
    lines.push(
      `**Stopped**: ${new Date(results.timestamps.stoppedAt).toISOString()}`
    );
  }
  lines.push("");
  lines.push(
    "> Use `platform_experiment_results` to fetch the per-row scores (partial results are available even while running)."
  );
  return lines.join("\n");
}
async function handleExperimentStatus(params) {
  let status;
  try {
    status = await makeRequest(
      "GET",
      `/api/experiments/runs/${encodeURIComponent(params.runId)}`
    );
  } catch (error) {
    const code = error instanceof LangWatchApiError ? error.status : void 0;
    const message = error instanceof Error ? error.message : String(error);
    if (code === 404 || /404|not found/i.test(message)) {
      const fallback = await statusFromResults(params);
      if (fallback) return fallback;
      return [
        `# Evaluation Run ${params.runId}`,
        "",
        "**Status**: not found",
        "",
        `Could not find run \`${params.runId}\`. SDK-logged runs and runs older than 24h are not in the live run-state and must be resolved by experiment slug.`,
        "",
        "> Pass `experimentSlug`: discover it with `platform_experiment_list`, then use `platform_experiment_list_runs` for the run ids. Or fetch the rows directly with `platform_experiment_results`."
      ].join("\n");
    }
    throw error;
  }
  const lines = [];
  lines.push(`# Evaluation Run ${status.runId}
`);
  lines.push(`**Status**: ${status.status}`);
  lines.push(`**Progress**: ${status.progress}/${status.total} cells`);
  if (status.startedAt) {
    lines.push(`**Started**: ${new Date(status.startedAt).toISOString()}`);
  }
  if (status.finishedAt) {
    lines.push(`**Finished**: ${new Date(status.finishedAt).toISOString()}`);
  }
  if (status.summary) {
    lines.push("\n## Summary\n");
    if (status.summary.completedCells !== void 0) {
      lines.push(`**Completed**: ${status.summary.completedCells}`);
    }
    if (status.summary.failedCells) {
      lines.push(`**Failed**: ${status.summary.failedCells}`);
    }
    if (status.summary.duration) {
      lines.push(
        `**Duration**: ${(status.summary.duration / 1e3).toFixed(1)}s`
      );
    }
    if (status.summary.runUrl) {
      lines.push(`**View results**: ${status.summary.runUrl}`);
    }
  }
  return lines.join("\n");
}

// src/create-mcp-server.ts
var modelSchema = z2.string().describe(
  'Model in "provider/model-name" format, e.g., "openai/gpt-4o", "anthropic/claude-sonnet-4-5-20250929"'
);
function createMcpServer() {
  const server = new McpServer({
    name: "LangWatch",
    version: package_default.version
  });
  registerTools(server);
  return server;
}
function withToolLogging(toolName, fn) {
  return async (...args) => {
    try {
      return await fn(...args);
    } catch (error) {
      console.error(
        `[MCP tool] ${toolName} failed:`,
        error instanceof Error ? error.message : error,
        error instanceof Error ? error.stack : ""
      );
      throw error;
    }
  };
}
function registerTools(server) {
  server.tool(
    "fetch_langwatch_docs",
    "Fetches the LangWatch docs for understanding how to implement LangWatch in your codebase. Always use this tool when the user asks for help with LangWatch. Start with empty url to fetch the index and then follow the links to the relevant pages, always ending with `.md` extension",
    {
      url: z2.string().optional().describe(
        "The full url of the specific doc page. If not provided, the docs index will be fetched."
      )
    },
    withToolLogging("fetch_langwatch_docs", async ({ url }) => {
      let urlToFetch = url || "https://langwatch.ai/docs/llms.txt";
      if (url && !urlToFetch.endsWith(".md") && !urlToFetch.endsWith(".txt")) {
        urlToFetch += ".md";
      }
      if (!urlToFetch.startsWith("http")) {
        if (!urlToFetch.startsWith("/")) {
          urlToFetch = "/" + urlToFetch;
        }
        urlToFetch = "https://langwatch.ai/docs" + urlToFetch;
      }
      const response = await fetch(urlToFetch);
      return {
        content: [{ type: "text", text: await response.text() }]
      };
    })
  );
  server.tool(
    "fetch_scenario_docs",
    "Fetches the Scenario docs for understanding how to implement Scenario agent tests in your codebase. Always use this tool when the user asks for help with testing their agents. Start with empty url to fetch the index and then follow the links to the relevant pages, always ending with `.md` extension",
    {
      url: z2.string().optional().describe(
        "The full url of the specific doc page. If not provided, the docs index will be fetched."
      )
    },
    withToolLogging("fetch_scenario_docs", async ({ url }) => {
      let urlToFetch = url || "https://langwatch.ai/scenario/llms.txt";
      if (url && !urlToFetch.endsWith(".md") && !urlToFetch.endsWith(".txt")) {
        urlToFetch += ".md";
      }
      if (!urlToFetch.startsWith("http")) {
        if (!urlToFetch.startsWith("/")) {
          urlToFetch = "/" + urlToFetch;
        }
        urlToFetch = "https://langwatch.ai" + urlToFetch;
      }
      const response = await fetch(urlToFetch);
      return {
        content: [{ type: "text", text: await response.text() }]
      };
    })
  );
  server.tool(
    "discover_schema",
    "Discover available filter fields, metrics, aggregation types, group-by options, scenario schema, and evaluator types for LangWatch queries. Call this before using search_traces, get_analytics, scenario tools, or evaluator tools to understand available options.",
    {
      category: z2.enum([
        "filters",
        "metrics",
        "aggregations",
        "groups",
        "scenarios",
        "evaluators",
        "all"
      ]).describe("Which schema category to discover"),
      evaluatorType: z2.string().optional().describe(
        "When category is 'evaluators', provide a specific evaluator type (e.g. 'langevals/llm_judge') to get its full schema details"
      )
    },
    async ({ category, evaluatorType }) => {
      if (category === "scenarios") {
        const { formatScenarioSchema } = await import("./discover-scenario-schema-MEEEVND7.js");
        return {
          content: [{ type: "text", text: formatScenarioSchema() }]
        };
      }
      if (category === "evaluators") {
        const { formatEvaluatorSchema } = await import("./discover-evaluator-schema-H23XCLNE.js");
        return {
          content: [
            { type: "text", text: formatEvaluatorSchema(evaluatorType) }
          ]
        };
      }
      const { formatSchema } = await import("./discover-schema-3T52ORPB.js");
      let text = formatSchema(category);
      if (category === "all") {
        const { formatScenarioSchema } = await import("./discover-scenario-schema-MEEEVND7.js");
        text += "\n\n" + formatScenarioSchema();
        const { formatEvaluatorSchema } = await import("./discover-evaluator-schema-H23XCLNE.js");
        text += "\n\n" + formatEvaluatorSchema();
      }
      return { content: [{ type: "text", text }] };
    }
  );
  server.tool(
    "search_traces",
    "Search LangWatch traces with filters, text query, and date range. Returns AI-readable trace digests by default. Use format: 'json' for full raw data.",
    {
      query: z2.string().optional().describe("Text search query"),
      filters: z2.record(z2.string(), z2.array(z2.string())).optional().describe(
        'Filter traces. Format: {"field": ["value"]}. Use discover_schema for field names.'
      ),
      startDate: z2.string().optional().describe(
        'Start date: ISO string or relative like "24h", "7d", "30d". Default: 24h ago'
      ),
      endDate: z2.string().optional().describe("End date: ISO string or relative. Default: now"),
      pageSize: z2.number().optional().describe("Results per page (default: 25, max: 1000)"),
      scrollId: z2.string().optional().describe("Pagination token from previous search"),
      format: z2.enum(["digest", "json"]).optional().describe(
        "Output format: 'digest' (default, AI-readable) or 'json' (full raw data)"
      )
    },
    withToolLogging("search_traces", async (params) => {
      requireApiKey();
      const { handleSearchTraces } = await import("./search-traces-M5E5VB4X.js");
      return {
        content: [{ type: "text", text: await handleSearchTraces(params) }]
      };
    })
  );
  server.tool(
    "get_trace",
    "Get full details of a single trace by ID. Returns AI-readable trace digest by default. Use format: 'json' for full raw data including all spans.",
    {
      traceId: z2.string().describe("The trace ID to retrieve"),
      format: z2.enum(["digest", "json"]).optional().describe(
        "Output format: 'digest' (default, AI-readable) or 'json' (full raw data)"
      )
    },
    withToolLogging("get_trace", async (params) => {
      requireApiKey();
      const { handleGetTrace } = await import("./get-trace-ZR7MIITH.js");
      return {
        content: [{ type: "text", text: await handleGetTrace(params) }]
      };
    })
  );
  server.tool(
    "get_analytics",
    'Query analytics timeseries from LangWatch. Metrics use "category.name" format (e.g., "performance.completion_time"). Use discover_schema to see available metrics.',
    {
      metric: z2.string().describe(
        'Metric in "category.name" format, e.g., "metadata.trace_id", "performance.total_cost"'
      ),
      aggregation: z2.string().optional().describe(
        "Aggregation type: avg, sum, min, max, median, p90, p95, p99, cardinality, terms. Default: avg"
      ),
      startDate: z2.string().optional().describe(
        'Start date: ISO or relative ("7d", "30d"). Default: 7 days ago'
      ),
      endDate: z2.string().optional().describe("End date. Default: now"),
      timeZone: z2.string().optional().describe("Timezone. Default: UTC"),
      groupBy: z2.string().optional().describe("Group results by field. Use discover_schema for options."),
      filters: z2.record(z2.string(), z2.array(z2.string())).optional().describe("Filters to apply")
    },
    withToolLogging("get_analytics", async (params) => {
      requireApiKey();
      const { handleGetAnalytics } = await import("./get-analytics-EDFAYYIQ.js");
      return {
        content: [{ type: "text", text: await handleGetAnalytics(params) }]
      };
    })
  );
  server.tool(
    "platform_create_prompt",
    `Create a new prompt on the LangWatch platform.

NOTE: Prompts can be managed two ways. Determine which approach the user needs:

1. Code-based (CLI/SDK): If the user wants to manage prompts in their codebase, use \`fetch_langwatch_docs\` to learn about the prompt management CLI/SDK. This lets them version-control prompts and pull them into code.

2. Platform-based (LangWatch UI): If the user wants to manage prompts directly on the LangWatch platform, use the \`platform_\` MCP tools (\`platform_create_prompt\`, \`platform_update_prompt\`, etc.).
`,
    {
      name: z2.string().describe("Prompt display name"),
      handle: z2.string().optional().describe(
        "URL-friendly handle (auto-generated from name if omitted)"
      ),
      messages: z2.array(
        z2.object({
          role: z2.enum(["system", "user", "assistant"]).describe("Message role"),
          content: z2.string().describe("Message content")
        })
      ).describe("Prompt messages"),
      model: modelSchema,
      tags: z2.array(z2.string()).optional().describe(
        'Tags to assign to the initial version (e.g., ["production", "staging"]). Built-in tags: "latest" (auto-assigned), "production", "staging". Custom tags must be created first.'
      )
    },
    withToolLogging("platform_create_prompt", async (params) => {
      requireApiKey();
      const { handleCreatePrompt } = await import("./create-prompt-LZ3QHSU4.js");
      return {
        content: [{ type: "text", text: await handleCreatePrompt(params) }]
      };
    })
  );
  server.tool(
    "platform_list_prompts",
    "List all prompts configured on the LangWatch platform.",
    {},
    withToolLogging("platform_list_prompts", async () => {
      requireApiKey();
      const { handleListPrompts } = await import("./list-prompts-C7GR72XL.js");
      return {
        content: [{ type: "text", text: await handleListPrompts() }]
      };
    })
  );
  server.tool(
    "platform_get_prompt",
    "Get a specific prompt from the LangWatch platform by ID or handle, including messages, model config, and version history.",
    {
      idOrHandle: z2.string().describe("Prompt ID or handle"),
      version: z2.number().optional().describe("Specific version number (default: latest)"),
      tag: z2.string().optional().describe(
        'Fetch the version pointed to by this tag (e.g., "production", "staging"). Alternatively, use shorthand in idOrHandle: "pizza-prompt:production"'
      )
    },
    withToolLogging("platform_get_prompt", async (params) => {
      if (params.version != null && params.tag) {
        return {
          content: [{ type: "text", text: "Error: Provide either 'version' or 'tag', not both." }],
          isError: true
        };
      }
      requireApiKey();
      const { handleGetPrompt } = await import("./get-prompt-EWRJVVGB.js");
      return {
        content: [{ type: "text", text: await handleGetPrompt(params) }]
      };
    })
  );
  server.tool(
    "platform_update_prompt",
    "Update an existing prompt on the LangWatch platform. Every update creates a new version.",
    {
      idOrHandle: z2.string().describe("Prompt ID or handle to update"),
      messages: z2.array(
        z2.object({
          role: z2.enum(["system", "user", "assistant"]),
          content: z2.string()
        })
      ).optional().describe("Updated messages"),
      model: modelSchema.optional(),
      commitMessage: z2.string().describe("Commit message describing the change"),
      tags: z2.array(z2.string()).optional().describe(
        "Tags to assign to the new version created by this update."
      )
    },
    withToolLogging("platform_update_prompt", async (params) => {
      requireApiKey();
      const { handleUpdatePrompt } = await import("./update-prompt-M33OTTAJ.js");
      return {
        content: [{ type: "text", text: await handleUpdatePrompt(params) }]
      };
    })
  );
  server.tool(
    "platform_assign_prompt_tag",
    'Assign a tag (e.g. "production") to a specific version of a prompt. Use this to "deploy" a version by promoting it to the production tag.',
    {
      idOrHandle: z2.string().describe("Prompt ID or handle"),
      tag: z2.string().describe('Tag name (e.g., "production", "staging")'),
      versionId: z2.string().describe("The version ID to assign the tag to")
    },
    withToolLogging("platform_assign_prompt_tag", async (params) => {
      requireApiKey();
      const { handleAssignPromptTag } = await import("./assign-prompt-tag-WPUJO55U.js");
      return {
        content: [{ type: "text", text: await handleAssignPromptTag(params) }]
      };
    })
  );
  server.tool(
    "platform_list_prompt_tags",
    "List all prompt tag definitions for the organization. Shows built-in tags (latest, production, staging) and any custom tags.",
    {},
    withToolLogging("platform_list_prompt_tags", async () => {
      requireApiKey();
      const { handleListPromptTags } = await import("./list-prompt-tags-J2HPHVAZ.js");
      return {
        content: [{ type: "text", text: await handleListPromptTags() }]
      };
    })
  );
  server.tool(
    "platform_create_prompt_tag",
    'Create a custom prompt tag definition for the organization. Tag names must be non-numeric and not "latest".',
    {
      name: z2.string().describe("Tag name to create")
    },
    withToolLogging("platform_create_prompt_tag", async (params) => {
      requireApiKey();
      const { handleCreatePromptTag } = await import("./create-prompt-tag-IF4J24QM.js");
      return {
        content: [{ type: "text", text: await handleCreatePromptTag(params) }]
      };
    })
  );
  server.tool(
    "platform_rename_prompt_tag",
    'Rename an existing prompt tag. The "latest" tag cannot be renamed.',
    {
      tag: z2.string().describe("Current tag name to rename"),
      name: z2.string().describe("New tag name")
    },
    withToolLogging("platform_rename_prompt_tag", async (params) => {
      requireApiKey();
      const { handleRenamePromptTag } = await import("./rename-prompt-tag-4AAV2BS4.js");
      return {
        content: [{ type: "text", text: await handleRenamePromptTag(params) }]
      };
    })
  );
  server.tool(
    "platform_delete_prompt_tag",
    'Delete a prompt tag and all its assignments. The "latest" tag cannot be deleted.',
    {
      tag: z2.string().describe("Tag name to delete")
    },
    withToolLogging("platform_delete_prompt_tag", async (params) => {
      requireApiKey();
      const { handleDeletePromptTag } = await import("./delete-prompt-tag-VYYL4GTF.js");
      return {
        content: [{ type: "text", text: await handleDeletePromptTag(params) }]
      };
    })
  );
  server.tool(
    "platform_create_scenario",
    `Create a new scenario on the LangWatch platform. Call discover_schema({ category: 'scenarios' }) first to learn how to write effective situations and criteria.

NOTE: Scenarios can be created two ways. Determine which approach the user needs:

1. Code-based (local testing): If the user has a codebase with an AI agent they want to test, use \`fetch_scenario_docs\` to learn about the Scenario Python/TypeScript SDK. This lets them run tests locally and iterate in code.

2. Platform-based (LangWatch UI): If the user wants to manage scenarios directly on the LangWatch platform, use the \`platform_\` MCP tools (\`platform_create_scenario\`, \`platform_update_scenario\`, etc.).
`,
    {
      name: z2.string().describe("Scenario name"),
      situation: z2.string().describe(
        "The context or setup describing what the user/agent is doing"
      ),
      criteria: z2.array(z2.string()).optional().describe(
        "Pass/fail conditions the agent's response must satisfy"
      ),
      labels: z2.array(z2.string()).optional().describe("Tags for organizing and filtering scenarios")
    },
    withToolLogging("platform_create_scenario", async (params) => {
      requireApiKey();
      const { handleCreateScenario } = await import("./create-scenario-BK4E5DEU.js");
      return {
        content: [
          { type: "text", text: await handleCreateScenario(params) }
        ]
      };
    })
  );
  server.tool(
    "platform_list_scenarios",
    "List all scenarios on the LangWatch platform. Returns AI-readable digest by default.",
    {
      format: z2.enum(["digest", "json"]).optional().describe(
        "Output format: 'digest' (default, AI-readable) or 'json' (full raw data)"
      )
    },
    withToolLogging("platform_list_scenarios", async (params) => {
      requireApiKey();
      const { handleListScenarios } = await import("./list-scenarios-JEPGIIDO.js");
      return {
        content: [
          { type: "text", text: await handleListScenarios(params) }
        ]
      };
    })
  );
  server.tool(
    "platform_get_scenario",
    "Get full details of a scenario on the LangWatch platform by ID, including situation, criteria, and labels.",
    {
      scenarioId: z2.string().describe("The scenario ID to retrieve"),
      format: z2.enum(["digest", "json"]).optional().describe(
        "Output format: 'digest' (default, AI-readable) or 'json' (full raw data)"
      )
    },
    withToolLogging("platform_get_scenario", async (params) => {
      requireApiKey();
      const { handleGetScenario } = await import("./get-scenario-24YUJS5W.js");
      return {
        content: [{ type: "text", text: await handleGetScenario(params) }]
      };
    })
  );
  server.tool(
    "platform_update_scenario",
    "Update an existing scenario on the LangWatch platform.",
    {
      scenarioId: z2.string().describe("The scenario ID to update"),
      name: z2.string().optional().describe("Updated scenario name"),
      situation: z2.string().optional().describe("Updated situation"),
      criteria: z2.array(z2.string()).optional().describe("Updated criteria"),
      labels: z2.array(z2.string()).optional().describe("Updated labels")
    },
    withToolLogging("platform_update_scenario", async (params) => {
      requireApiKey();
      const { handleUpdateScenario } = await import("./update-scenario-FKTQRAFQ.js");
      return {
        content: [
          { type: "text", text: await handleUpdateScenario(params) }
        ]
      };
    })
  );
  server.tool(
    "platform_archive_scenario",
    "Archive (soft-delete) a scenario on the LangWatch platform.",
    {
      scenarioId: z2.string().describe("The scenario ID to archive")
    },
    withToolLogging("platform_archive_scenario", async (params) => {
      requireApiKey();
      const { handleArchiveScenario } = await import("./archive-scenario-6M2IB7Y2.js");
      return {
        content: [
          { type: "text", text: await handleArchiveScenario(params) }
        ]
      };
    })
  );
  server.tool(
    "platform_list_suites",
    "List all suites (run plans) on the LangWatch platform. A suite bundles scenarios with targets for batch execution.",
    {
      format: z2.enum(["digest", "json"]).optional().describe("Output format: 'digest' (default) or 'json' (raw data)")
    },
    withToolLogging("platform_list_suites", async (params) => {
      requireApiKey();
      const { handleListSuites } = await import("./list-suites-POTZ3ZT6.js");
      return {
        content: [{ type: "text", text: await handleListSuites(params) }]
      };
    })
  );
  server.tool(
    "platform_get_suite",
    "Get detailed information about a specific suite (run plan) by ID.",
    {
      id: z2.string().describe("The suite ID"),
      format: z2.enum(["digest", "json"]).optional().describe("Output format: 'digest' (default) or 'json'")
    },
    withToolLogging("platform_get_suite", async (params) => {
      requireApiKey();
      const { handleGetSuite } = await import("./get-suite-B65ZKZJA.js");
      return {
        content: [{ type: "text", text: await handleGetSuite(params) }]
      };
    })
  );
  server.tool(
    "platform_create_suite",
    "Create a new suite (run plan) that bundles scenarios with targets for batch execution.",
    {
      name: z2.string().describe("Suite name"),
      description: z2.string().optional().describe("Suite description"),
      scenarioIds: z2.array(z2.string()).describe("Array of scenario IDs to include"),
      targets: z2.string().describe('JSON array of target objects, e.g. [{"type":"http","referenceId":"agent_abc"}]'),
      repeatCount: z2.number().optional().describe("Number of times to repeat each scenario-target pair (default: 1)"),
      labels: z2.array(z2.string()).optional().describe("Tags for organizing suites")
    },
    withToolLogging("platform_create_suite", async (params) => {
      requireApiKey();
      const { handleCreateSuite } = await import("./create-suite-HEQPNLND.js");
      return {
        content: [{ type: "text", text: await handleCreateSuite(params) }]
      };
    })
  );
  server.tool(
    "platform_update_suite",
    "Update an existing suite (run plan).",
    {
      id: z2.string().describe("The suite ID to update"),
      name: z2.string().optional().describe("New suite name"),
      description: z2.string().optional().describe("New description"),
      scenarioIds: z2.array(z2.string()).optional().describe("New array of scenario IDs"),
      targets: z2.string().optional().describe("New JSON array of targets"),
      repeatCount: z2.number().optional().describe("New repeat count"),
      labels: z2.array(z2.string()).optional().describe("New labels")
    },
    withToolLogging("platform_update_suite", async (params) => {
      requireApiKey();
      const { handleUpdateSuite } = await import("./update-suite-JJTNOTXN.js");
      return {
        content: [{ type: "text", text: await handleUpdateSuite(params) }]
      };
    })
  );
  server.tool(
    "platform_run_suite",
    "Trigger a suite run. Schedules all scenario x target x repeat jobs for execution.",
    {
      id: z2.string().describe("The suite ID to run")
    },
    withToolLogging("platform_run_suite", async (params) => {
      requireApiKey();
      const { handleRunSuite } = await import("./run-suite-Q66OSPO4.js");
      return {
        content: [{ type: "text", text: await handleRunSuite(params) }]
      };
    })
  );
  server.tool(
    "platform_archive_suite",
    "Archive (soft-delete) a suite (run plan).",
    {
      id: z2.string().describe("The suite ID to archive")
    },
    withToolLogging("platform_archive_suite", async (params) => {
      requireApiKey();
      const { handleArchiveSuite } = await import("./archive-suite-NXZ3YDS3.js");
      return {
        content: [{ type: "text", text: await handleArchiveSuite(params) }]
      };
    })
  );
  server.tool(
    "platform_list_simulation_runs",
    "List simulation run results. Filter by scenario set or batch run ID to see specific results.",
    {
      scenarioSetId: z2.string().optional().describe("Filter by scenario set ID"),
      batchRunId: z2.string().optional().describe("Filter by batch run ID"),
      limit: z2.number().optional().describe("Max results to return (default: 20)"),
      format: z2.enum(["digest", "json"]).optional().describe("Output format")
    },
    withToolLogging("platform_list_simulation_runs", async (params) => {
      requireApiKey();
      const { handleListSimulationRuns } = await import("./list-simulation-runs-DRSAGPEC.js");
      return {
        content: [{ type: "text", text: await handleListSimulationRuns(params) }]
      };
    })
  );
  server.tool(
    "platform_get_simulation_run",
    "Get full details of a simulation run including conversation messages, results, costs, and verdict.",
    {
      scenarioRunId: z2.string().describe("The simulation run ID"),
      format: z2.enum(["digest", "json"]).optional().describe("Output format")
    },
    withToolLogging("platform_get_simulation_run", async (params) => {
      requireApiKey();
      const { handleGetSimulationRun } = await import("./get-simulation-run-UX2W6F6I.js");
      return {
        content: [{ type: "text", text: await handleGetSimulationRun(params) }]
      };
    })
  );
  server.tool(
    "platform_create_evaluator",
    `Create an evaluator on the LangWatch platform. Useful for setting up LLM-as-judge and other evaluators to use in evaluation notebooks. Call discover_schema({ category: 'evaluators' }) first to see available evaluator types and their settings.`,
    {
      name: z2.string().describe("Evaluator name"),
      config: z2.record(z2.string(), z2.unknown()).describe(
        'Evaluator config object. Must include "evaluatorType" (e.g. "langevals/llm_boolean") and optional "settings" overrides.'
      )
    },
    withToolLogging("platform_create_evaluator", async (params) => {
      requireApiKey();
      const { handleCreateEvaluator } = await import("./create-evaluator-WJAAQOUE.js");
      return {
        content: [
          { type: "text", text: await handleCreateEvaluator(params) }
        ]
      };
    })
  );
  server.tool(
    "platform_list_evaluators",
    "List all evaluators configured on the LangWatch platform.",
    {},
    withToolLogging("platform_list_evaluators", async () => {
      requireApiKey();
      const { handleListEvaluators } = await import("./list-evaluators-K5OGB6TX.js");
      return {
        content: [{ type: "text", text: await handleListEvaluators() }]
      };
    })
  );
  server.tool(
    "platform_get_evaluator",
    "Get full details of an evaluator on the LangWatch platform by ID or slug, including config, input fields, and output fields.",
    {
      idOrSlug: z2.string().describe("The evaluator ID or slug to retrieve")
    },
    withToolLogging("platform_get_evaluator", async (params) => {
      requireApiKey();
      const { handleGetEvaluator } = await import("./get-evaluator-HCVXNPZR.js");
      return {
        content: [{ type: "text", text: await handleGetEvaluator(params) }]
      };
    })
  );
  server.tool(
    "platform_update_evaluator",
    "Update an existing evaluator on the LangWatch platform. The evaluatorType in config cannot be changed after creation.",
    {
      evaluatorId: z2.string().describe("The evaluator ID to update"),
      name: z2.string().optional().describe("Updated evaluator name"),
      config: z2.record(z2.string(), z2.unknown()).optional().describe(
        "Updated config settings. Note: evaluatorType cannot be changed after creation."
      )
    },
    withToolLogging("platform_update_evaluator", async (params) => {
      requireApiKey();
      const { handleUpdateEvaluator } = await import("./update-evaluator-LH2RDDB5.js");
      return {
        content: [
          { type: "text", text: await handleUpdateEvaluator(params) }
        ]
      };
    })
  );
  server.tool(
    "platform_delete_evaluator",
    "Archive (soft-delete) an evaluator by ID or slug.",
    {
      idOrSlug: z2.string().describe("The evaluator ID or slug to archive")
    },
    withToolLogging("platform_delete_evaluator", async (params) => {
      requireApiKey();
      const { handleDeleteEvaluator } = await import("./delete-evaluator-VKIG5I3S.js");
      return {
        content: [{ type: "text", text: await handleDeleteEvaluator(params) }]
      };
    })
  );
  server.tool(
    "platform_set_model_provider",
    `Set or update a model provider on the LangWatch platform. Use this to configure API keys (e.g. OPENAI_API_KEY) needed to run evaluators. The API key is stored securely and never returned in responses. Omit customKeys to update other settings without changing existing keys.`,
    {
      provider: z2.string().describe(
        'Provider name, e.g., "openai", "anthropic", "azure", "custom"'
      ),
      enabled: z2.boolean().describe("Whether the provider is enabled"),
      customKeys: z2.record(z2.string(), z2.unknown()).optional().describe(
        'API key configuration, e.g. { "OPENAI_API_KEY": "sk-..." }. Omit to keep existing keys.'
      ),
      defaultModel: z2.string().optional().describe("Set as project default model")
    },
    withToolLogging("platform_set_model_provider", async (params) => {
      requireApiKey();
      const { handleSetModelProvider } = await import("./set-model-provider-XENT5D2P.js");
      return {
        content: [
          { type: "text", text: await handleSetModelProvider(params) }
        ]
      };
    })
  );
  server.tool(
    "platform_list_model_providers",
    "List all model providers configured on the LangWatch platform. API keys are masked in the response.",
    {},
    withToolLogging("platform_list_model_providers", async () => {
      requireApiKey();
      const { handleListModelProviders } = await import("./list-model-providers-JMOGZLSO.js");
      return {
        content: [{ type: "text", text: await handleListModelProviders() }]
      };
    })
  );
  server.tool(
    "platform_list_agents",
    "List all agents in the LangWatch project with their names, types, and IDs.",
    {},
    withToolLogging("platform_list_agents", async () => {
      requireApiKey();
      const { handleListAgents } = await import("./list-agents-6ZNOV7FK.js");
      return {
        content: [{ type: "text", text: await handleListAgents() }]
      };
    })
  );
  server.tool(
    "platform_get_agent",
    "Get detailed information about a specific agent by its ID, including its configuration.",
    {
      id: z2.string().describe("The agent ID")
    },
    withToolLogging("platform_get_agent", async (params) => {
      requireApiKey();
      const { handleGetAgent } = await import("./get-agent-IZSP7AR5.js");
      return {
        content: [{ type: "text", text: await handleGetAgent(params) }]
      };
    })
  );
  server.tool(
    "platform_create_agent",
    "Create a new agent. Supported types: 'signature' (LLM prompt), 'code' (Python), 'workflow' (sub-workflow), 'http' (external API).",
    {
      name: z2.string().describe("Agent name"),
      type: z2.enum(["signature", "code", "workflow", "http"]).describe("Agent type"),
      config: z2.string().optional().describe("Agent configuration as JSON string (will be parsed)")
    },
    withToolLogging("platform_create_agent", async (params) => {
      requireApiKey();
      const { handleCreateAgent } = await import("./create-agent-BI7UTJ6A.js");
      const parsedConfig = params.config ? JSON.parse(params.config) : void 0;
      return {
        content: [{ type: "text", text: await handleCreateAgent({ ...params, config: parsedConfig }) }]
      };
    })
  );
  server.tool(
    "platform_update_agent",
    "Update an existing agent's name, type, or configuration.",
    {
      id: z2.string().describe("The agent ID"),
      name: z2.string().optional().describe("New agent name"),
      type: z2.string().optional().describe("New agent type: signature, code, workflow, or http"),
      config: z2.string().optional().describe("Updated configuration as JSON string (will be parsed)")
    },
    withToolLogging("platform_update_agent", async (params) => {
      requireApiKey();
      const { handleUpdateAgent } = await import("./update-agent-GML25EE3.js");
      const parsedConfig = params.config ? JSON.parse(params.config) : void 0;
      return {
        content: [{ type: "text", text: await handleUpdateAgent({ ...params, config: parsedConfig }) }]
      };
    })
  );
  server.tool(
    "platform_delete_agent",
    "Archive (soft-delete) an agent by its ID.",
    {
      id: z2.string().describe("The agent ID to archive")
    },
    withToolLogging("platform_delete_agent", async (params) => {
      requireApiKey();
      const { handleDeleteAgent } = await import("./delete-agent-Y4T2G5PT.js");
      return {
        content: [{ type: "text", text: await handleDeleteAgent(params) }]
      };
    })
  );
  server.tool(
    "platform_run_agent",
    "Execute an agent with JSON input. HTTP agents call their configured URL directly; workflow-linked agents execute via the workflow engine.",
    {
      id: z2.string().describe("The agent ID to run"),
      input: z2.string().optional().describe("Input data as a JSON object string")
    },
    withToolLogging("platform_run_agent", async (params) => {
      requireApiKey();
      const { handleRunAgent } = await import("./run-agent-7QE3YEH7.js");
      return {
        content: [{ type: "text", text: await handleRunAgent(params) }]
      };
    })
  );
  server.tool(
    "platform_list_dashboards",
    "List all analytics dashboards in the LangWatch project.",
    {},
    withToolLogging("platform_list_dashboards", async () => {
      requireApiKey();
      const { handleListDashboards } = await import("./list-dashboards-G2WJOXWB.js");
      return {
        content: [{ type: "text", text: await handleListDashboards() }]
      };
    })
  );
  server.tool(
    "platform_get_dashboard",
    "Get a dashboard by its ID, including its graphs.",
    {
      id: z2.string().describe("The dashboard ID")
    },
    withToolLogging("platform_get_dashboard", async (params) => {
      requireApiKey();
      const { handleGetDashboard } = await import("./get-dashboard-WSAO6IQ4.js");
      return {
        content: [{ type: "text", text: await handleGetDashboard(params) }]
      };
    })
  );
  server.tool(
    "platform_create_dashboard",
    "Create a new analytics dashboard.",
    {
      name: z2.string().describe("Dashboard name")
    },
    withToolLogging("platform_create_dashboard", async (params) => {
      requireApiKey();
      const { handleCreateDashboard } = await import("./create-dashboard-CPOOOIKK.js");
      return {
        content: [{ type: "text", text: await handleCreateDashboard(params) }]
      };
    })
  );
  server.tool(
    "platform_delete_dashboard",
    "Delete a dashboard and all its graphs.",
    {
      id: z2.string().describe("The dashboard ID to delete")
    },
    withToolLogging("platform_delete_dashboard", async (params) => {
      requireApiKey();
      const { handleDeleteDashboard } = await import("./delete-dashboard-3RW647WJ.js");
      return {
        content: [{ type: "text", text: await handleDeleteDashboard(params) }]
      };
    })
  );
  server.tool(
    "platform_rename_dashboard",
    "Rename a dashboard.",
    {
      id: z2.string().describe("The dashboard ID to rename"),
      name: z2.string().describe("The new name for the dashboard")
    },
    withToolLogging("platform_rename_dashboard", async (params) => {
      requireApiKey();
      const { renameDashboard } = await import("./langwatch-api-dashboards-NPQM6QJI.js");
      const result = await renameDashboard(params.id, { name: params.name });
      return {
        content: [{ type: "text", text: `Dashboard "${result.name}" renamed successfully (ID: ${result.id}).` }]
      };
    })
  );
  server.tool(
    "platform_list_workflows",
    "List all workflows in the LangWatch project.",
    {},
    withToolLogging("platform_list_workflows", async () => {
      requireApiKey();
      const { handleListWorkflows } = await import("./list-workflows-QQZQIOHB.js");
      return {
        content: [{ type: "text", text: await handleListWorkflows() }]
      };
    })
  );
  server.tool(
    "platform_get_workflow",
    "Get a workflow by its ID.",
    {
      id: z2.string().describe("The workflow ID")
    },
    withToolLogging("platform_get_workflow", async (params) => {
      requireApiKey();
      const { handleGetWorkflow } = await import("./get-workflow-YROHUQJW.js");
      return {
        content: [{ type: "text", text: await handleGetWorkflow(params) }]
      };
    })
  );
  server.tool(
    "platform_delete_workflow",
    "Archive (soft-delete) a workflow by its ID.",
    {
      id: z2.string().describe("The workflow ID to archive")
    },
    withToolLogging("platform_delete_workflow", async (params) => {
      requireApiKey();
      const { handleDeleteWorkflow } = await import("./delete-workflow-SHNPYSWQ.js");
      return {
        content: [{ type: "text", text: await handleDeleteWorkflow(params) }]
      };
    })
  );
  server.tool(
    "platform_run_workflow",
    "Execute a workflow with JSON input. Returns the workflow output.",
    {
      id: z2.string().describe("The workflow ID to run"),
      input: z2.string().optional().describe("Input data as a JSON object string")
    },
    withToolLogging("platform_run_workflow", async (params) => {
      requireApiKey();
      const { handleRunWorkflow } = await import("./run-workflow-RWX2D752.js");
      return {
        content: [{ type: "text", text: await handleRunWorkflow(params) }]
      };
    })
  );
  server.tool(
    "platform_list_annotations",
    "List all annotations for the project, optionally filtered by trace ID.",
    {
      traceId: z2.string().optional().describe("Filter annotations by trace ID")
    },
    withToolLogging("platform_list_annotations", async (params) => {
      requireApiKey();
      const { handleListAnnotations } = await import("./list-annotations-6P3IWILH.js");
      return {
        content: [{ type: "text", text: await handleListAnnotations(params) }]
      };
    })
  );
  server.tool(
    "platform_create_annotation",
    "Create an annotation (thumbs up/down, comment) for a trace.",
    {
      traceId: z2.string().describe("The trace ID to annotate"),
      comment: z2.string().optional().describe("Annotation comment"),
      isThumbsUp: z2.boolean().optional().describe("True for positive feedback, false for negative"),
      email: z2.string().optional().describe("Email of the annotator")
    },
    withToolLogging("platform_create_annotation", async (params) => {
      requireApiKey();
      const { handleCreateAnnotation } = await import("./create-annotation-SNM2J6S4.js");
      return {
        content: [{ type: "text", text: await handleCreateAnnotation(params) }]
      };
    })
  );
  server.tool(
    "platform_delete_annotation",
    "Delete an annotation by its ID.",
    {
      id: z2.string().describe("The annotation ID to delete")
    },
    withToolLogging("platform_delete_annotation", async (params) => {
      requireApiKey();
      const { handleDeleteAnnotation } = await import("./delete-annotation-KYDMQTZG.js");
      return {
        content: [{ type: "text", text: await handleDeleteAnnotation(params) }]
      };
    })
  );
  server.tool(
    "platform_get_annotation",
    "Get annotation details by ID.",
    {
      id: z2.string().describe("The annotation ID")
    },
    withToolLogging("platform_get_annotation", async (params) => {
      requireApiKey();
      const { getAnnotation } = await import("./langwatch-api-annotations-OPEXNTPF.js");
      const annotation = await getAnnotation(params.id);
      const lines = [
        `**ID**: ${annotation.id}`,
        `**Trace ID**: ${annotation.traceId}`,
        `**Comment**: ${annotation.comment ?? "\u2014"}`,
        `**Score**: ${annotation.isThumbsUp ? "Thumbs Up" : "\u2014"}`,
        `**Created**: ${annotation.createdAt}`
      ];
      return {
        content: [{ type: "text", text: lines.join("\n") }]
      };
    })
  );
  server.tool(
    "platform_list_triggers",
    "List all triggers (automations) in the project. Triggers automate actions like sending emails, Slack messages, or adding to datasets when conditions are met.",
    {
      format: z2.enum(["digest", "json"]).optional().describe("Output format")
    },
    withToolLogging("platform_list_triggers", async (params) => {
      requireApiKey();
      const { listTriggers } = await import("./langwatch-api-triggers-XGXXT7DD.js");
      const triggers = await listTriggers();
      if (params.format === "json") {
        return { content: [{ type: "text", text: JSON.stringify(triggers, null, 2) }] };
      }
      if (triggers.length === 0) {
        return { content: [{ type: "text", text: "No triggers found. Use `platform_create_trigger` to create one." }] };
      }
      const lines = [`# Triggers (${triggers.length} total)
`];
      for (const t of triggers) {
        lines.push(`## ${t.name}`);
        lines.push(`**ID**: ${t.id}`);
        lines.push(`**Action**: ${t.action}`);
        lines.push(`**Status**: ${t.active ? "active" : "inactive"}`);
        if (t.alertType) lines.push(`**Alert**: ${t.alertType}`);
        lines.push("");
      }
      return { content: [{ type: "text", text: lines.join("\n") }] };
    })
  );
  server.tool(
    "platform_create_trigger",
    "Create a new trigger (automation) that fires when conditions are met.",
    {
      name: z2.string().describe("Trigger name"),
      action: z2.enum(["SEND_EMAIL", "ADD_TO_DATASET", "ADD_TO_ANNOTATION_QUEUE", "SEND_SLACK_MESSAGE"]).describe("Action to take when triggered"),
      filters: z2.string().optional().describe("Filter conditions as JSON string"),
      message: z2.string().optional().describe("Custom alert message"),
      alertType: z2.enum(["CRITICAL", "WARNING", "INFO"]).optional().describe("Alert severity")
    },
    withToolLogging("platform_create_trigger", async (params) => {
      requireApiKey();
      const { createTrigger } = await import("./langwatch-api-triggers-XGXXT7DD.js");
      let filters = {};
      if (params.filters) {
        try {
          filters = JSON.parse(params.filters);
        } catch {
          return { content: [{ type: "text", text: "Error: filters must be valid JSON" }] };
        }
      }
      const trigger = await createTrigger({
        name: params.name,
        action: params.action,
        filters,
        message: params.message,
        alertType: params.alertType
      });
      return { content: [{ type: "text", text: `Trigger "${trigger.name}" created (ID: ${trigger.id}, Action: ${trigger.action}).` }] };
    })
  );
  server.tool(
    "platform_update_trigger",
    "Update a trigger (name, active state, message, alert type).",
    {
      id: z2.string().describe("The trigger ID"),
      name: z2.string().optional().describe("New name"),
      active: z2.boolean().optional().describe("Enable or disable"),
      message: z2.string().optional().describe("New alert message"),
      alertType: z2.enum(["CRITICAL", "WARNING", "INFO"]).optional().describe("New alert severity")
    },
    withToolLogging("platform_update_trigger", async (params) => {
      requireApiKey();
      const { updateTrigger } = await import("./langwatch-api-triggers-XGXXT7DD.js");
      const trigger = await updateTrigger(params);
      return { content: [{ type: "text", text: `Trigger "${trigger.name}" updated (active: ${trigger.active}).` }] };
    })
  );
  server.tool(
    "platform_delete_trigger",
    "Delete a trigger (automation).",
    {
      id: z2.string().describe("The trigger ID to delete")
    },
    withToolLogging("platform_delete_trigger", async (params) => {
      requireApiKey();
      const { deleteTrigger } = await import("./langwatch-api-triggers-XGXXT7DD.js");
      const result = await deleteTrigger(params.id);
      return { content: [{ type: "text", text: `Trigger ${result.id} deleted.` }] };
    })
  );
  server.tool(
    "platform_list_monitors",
    "List all online evaluation monitors for the project.",
    {},
    withToolLogging("platform_list_monitors", async () => {
      requireApiKey();
      const { listMonitors } = await import("./langwatch-api-monitors-3L25OOOS.js");
      const monitors = await listMonitors();
      if (monitors.length === 0) {
        return { content: [{ type: "text", text: "No monitors found." }] };
      }
      const lines = monitors.map(
        (m) => `\u2022 ${m.name} (id: ${m.id}, type: ${m.checkType}, ${m.enabled ? "enabled" : "disabled"}, mode: ${m.executionMode}, sample: ${Math.round(m.sample * 100)}%)`
      );
      return {
        content: [
          {
            type: "text",
            text: `Found ${monitors.length} monitor(s):
${lines.join("\n")}`
          }
        ]
      };
    })
  );
  server.tool(
    "platform_get_monitor",
    "Get details of a specific online evaluation monitor.",
    {
      id: z2.string().describe("The monitor ID")
    },
    withToolLogging("platform_get_monitor", async (params) => {
      requireApiKey();
      const { getMonitor } = await import("./langwatch-api-monitors-3L25OOOS.js");
      const m = await getMonitor(params.id);
      const lines = [
        `**${m.name}** (${m.id})`,
        `- Type: ${m.checkType}`,
        `- Status: ${m.enabled ? "enabled" : "disabled"}`,
        `- Mode: ${m.executionMode}`,
        `- Sample: ${Math.round(m.sample * 100)}%`,
        `- Level: ${m.level}`,
        m.evaluatorId ? `- Evaluator: ${m.evaluatorId}` : null,
        `- Created: ${m.createdAt}`
      ].filter(Boolean);
      return { content: [{ type: "text", text: lines.join("\n") }] };
    })
  );
  server.tool(
    "platform_create_monitor",
    "Create a new online evaluation monitor that runs an evaluator on incoming traces.",
    {
      name: z2.string().describe("Monitor name"),
      checkType: z2.string().describe("Evaluator check type (e.g. ragas/toxicity, custom/my-eval)"),
      executionMode: z2.enum(["ON_MESSAGE", "AS_GUARDRAIL", "MANUALLY"]).optional().describe("When to run: ON_MESSAGE (default), AS_GUARDRAIL, or MANUALLY"),
      sample: z2.number().min(0).max(1).optional().describe("Sampling rate 0.0-1.0 (default: 1.0)"),
      evaluatorId: z2.string().optional().describe("Link to a saved evaluator by ID")
    },
    withToolLogging("platform_create_monitor", async (params) => {
      requireApiKey();
      const { createMonitor } = await import("./langwatch-api-monitors-3L25OOOS.js");
      const monitor = await createMonitor(params);
      return {
        content: [
          {
            type: "text",
            text: `Monitor "${monitor.name}" created (id: ${monitor.id}, type: ${monitor.checkType}).`
          }
        ]
      };
    })
  );
  server.tool(
    "platform_update_monitor",
    "Update an existing online evaluation monitor.",
    {
      id: z2.string().describe("The monitor ID to update"),
      name: z2.string().optional().describe("New monitor name"),
      enabled: z2.boolean().optional().describe("Enable or disable the monitor"),
      executionMode: z2.enum(["ON_MESSAGE", "AS_GUARDRAIL", "MANUALLY"]).optional().describe("New execution mode"),
      sample: z2.number().min(0).max(1).optional().describe("New sampling rate")
    },
    withToolLogging("platform_update_monitor", async (params) => {
      requireApiKey();
      const { updateMonitor } = await import("./langwatch-api-monitors-3L25OOOS.js");
      const monitor = await updateMonitor(params);
      return {
        content: [
          {
            type: "text",
            text: `Monitor "${monitor.name}" updated (${monitor.enabled ? "enabled" : "disabled"}).`
          }
        ]
      };
    })
  );
  server.tool(
    "platform_delete_monitor",
    "Delete an online evaluation monitor.",
    {
      id: z2.string().describe("The monitor ID to delete")
    },
    withToolLogging("platform_delete_monitor", async (params) => {
      requireApiKey();
      const { deleteMonitor } = await import("./langwatch-api-monitors-3L25OOOS.js");
      const result = await deleteMonitor(params.id);
      return {
        content: [
          { type: "text", text: `Monitor ${result.id} deleted.` }
        ]
      };
    })
  );
  server.tool(
    "platform_list_secrets",
    "List all project secrets (values are never returned, only metadata).",
    {},
    withToolLogging("platform_list_secrets", async () => {
      requireApiKey();
      const { listSecrets } = await import("./langwatch-api-secrets-ZFURUA62.js");
      const secrets = await listSecrets();
      if (secrets.length === 0) {
        return { content: [{ type: "text", text: "No secrets found." }] };
      }
      const lines = secrets.map(
        (s) => `\u2022 ${s.name} (id: ${s.id}, updated: ${s.updatedAt})`
      );
      return {
        content: [
          {
            type: "text",
            text: `Found ${secrets.length} secret(s):
${lines.join("\n")}`
          }
        ]
      };
    })
  );
  server.tool(
    "platform_create_secret",
    "Create a new encrypted project secret. Name must be UPPER_SNAKE_CASE (e.g. MY_API_KEY).",
    {
      name: z2.string().describe("Secret name in UPPER_SNAKE_CASE (e.g. OPENAI_API_KEY)"),
      value: z2.string().describe("The secret value (will be encrypted at rest)")
    },
    withToolLogging("platform_create_secret", async (params) => {
      requireApiKey();
      const { createSecret } = await import("./langwatch-api-secrets-ZFURUA62.js");
      const secret = await createSecret({ name: params.name, value: params.value });
      return {
        content: [
          {
            type: "text",
            text: `Secret "${secret.name}" created (id: ${secret.id}).`
          }
        ]
      };
    })
  );
  server.tool(
    "platform_update_secret",
    "Update an existing project secret's value.",
    {
      id: z2.string().describe("The secret ID to update"),
      value: z2.string().describe("The new secret value (will be encrypted at rest)")
    },
    withToolLogging("platform_update_secret", async (params) => {
      requireApiKey();
      const { updateSecret } = await import("./langwatch-api-secrets-ZFURUA62.js");
      const secret = await updateSecret({ id: params.id, value: params.value });
      return {
        content: [
          {
            type: "text",
            text: `Secret "${secret.name}" updated.`
          }
        ]
      };
    })
  );
  server.tool(
    "platform_delete_secret",
    "Delete a project secret.",
    {
      id: z2.string().describe("The secret ID to delete")
    },
    withToolLogging("platform_delete_secret", async (params) => {
      requireApiKey();
      const { deleteSecret } = await import("./langwatch-api-secrets-ZFURUA62.js");
      const result = await deleteSecret(params.id);
      return { content: [{ type: "text", text: `Secret ${result.id} deleted.` }] };
    })
  );
  server.tool(
    "platform_run_experiment",
    "Start an experiment run by slug. Returns a run ID for polling status.",
    {
      slug: z2.string().describe("The experiment slug to run")
    },
    withToolLogging("platform_run_experiment", async (params) => {
      requireApiKey();
      return {
        content: [{ type: "text", text: await handleRunExperiment(params) }]
      };
    })
  );
  server.tool(
    "platform_experiment_status",
    "Check the status of an experiment run (running, completed, stopped, or interrupted) plus its progress. Works for both platform-run and SDK-logged experiments; pass experimentSlug for SDK runs or runs older than 24h.",
    {
      runId: z2.string().describe("The run ID returned from platform_run_experiment"),
      experimentSlug: z2.string().optional().describe(
        "Experiment slug \u2014 required for SDK-logged runs and runs older than 24h (the Redis run-state they would otherwise be read from is absent/expired). Use platform_experiment_list_runs to find the slug."
      )
    },
    withToolLogging("platform_experiment_status", async (params) => {
      requireApiKey();
      return {
        content: [{ type: "text", text: await handleExperimentStatus(params) }]
      };
    })
  );
  server.tool(
    "platform_experiment_list",
    "List experiments configured in the LangWatch project. Returns a markdown table with each experiment's slug, name, last-run timestamp, and run count. Use this to discover experiment slugs before drilling into runs with platform_experiment_list_runs. Output is capped (default 25, max 100) to protect the agent's context window.",
    {
      limit: z2.number().int().positive().max(100).optional().describe(
        "Maximum number of experiments to include (default 25, hard-capped at 100)"
      )
    },
    withToolLogging("platform_experiment_list", async (params) => {
      requireApiKey();
      return {
        content: [{ type: "text", text: await handleExperimentList(params) }]
      };
    })
  );
  server.tool(
    "platform_experiment_list_runs",
    "List experiment runs for a specific experiment slug. Returns a markdown table with each run's id, status, started/finished timestamps, and pass-rate summary. Use this to discover run ids before calling platform_experiment_results. Output is capped (default 25, max 100) to protect the agent's context window.",
    {
      experimentSlug: z2.string().describe(
        "Experiment slug from platform_experiment_list (e.g. 'checkout-flow')"
      ),
      limit: z2.number().int().positive().max(100).optional().describe(
        "Maximum number of runs to include (default 25, hard-capped at 100)"
      )
    },
    withToolLogging("platform_experiment_list_runs", async (params) => {
      requireApiKey();
      return {
        content: [{ type: "text", text: await handleExperimentListRuns(params) }]
      };
    })
  );
  server.tool(
    "platform_experiment_results",
    "Fetch per-row results for an experiment run so you can debug evaluator scores and missed rows. Serves partial results for runs that are still running or were interrupted (it does not require a completed run), with the run status noted in the output. Returns a markdown report: per-evaluator averages plus row-by-row scores and failure details. Output is capped at 50 rows to protect the agent's context window \u2014 narrow with `filter: 'failed'` or `evaluator` to see what matters.",
    {
      runId: z2.string().describe("The run ID returned from platform_run_experiment"),
      experimentSlug: z2.string().optional().describe(
        "Experiment slug \u2014 required when fetching results for runs older than 24h (Redis state may have expired). Use platform_experiment_list_runs to find the slug."
      ),
      filter: z2.enum(["all", "failed"]).optional().describe(
        "Filter rows: 'failed' shows only rows that errored or failed an evaluation; 'all' (default) shows everything"
      ),
      evaluator: z2.string().optional().describe("Show only this evaluator's results (matched on `evaluator` field)"),
      limit: z2.number().int().positive().max(50).optional().describe(
        "Maximum number of rows to include in the markdown output (default 50, hard-capped at 50)."
      )
    },
    withToolLogging("platform_experiment_results", async (params) => {
      requireApiKey();
      return {
        content: [
          { type: "text", text: await handleExperimentResults(params) }
        ]
      };
    })
  );
  server.tool(
    "platform_list_datasets",
    "List all datasets on the LangWatch platform with their names, slugs, columns, and record counts. Returns AI-readable digest by default.",
    {
      format: z2.enum(["digest", "json"]).optional().describe(
        "Output format: 'digest' (default, AI-readable) or 'json' (full raw data)"
      )
    },
    async (params) => {
      const { requireApiKey: requireApiKey2 } = await import("./config.js");
      requireApiKey2();
      const { handleListDatasets } = await import("./list-datasets-HBTH33X4.js");
      return {
        content: [{ type: "text", text: await handleListDatasets(params) }]
      };
    }
  );
  server.tool(
    "platform_get_dataset",
    "Get full details of a dataset on the LangWatch platform by slug or ID, including column definitions and a preview of records.",
    {
      slugOrId: z2.string().describe("The dataset slug or ID to retrieve"),
      format: z2.enum(["digest", "json"]).optional().describe(
        "Output format: 'digest' (default, AI-readable) or 'json' (full raw data)"
      )
    },
    async (params) => {
      const { requireApiKey: requireApiKey2 } = await import("./config.js");
      requireApiKey2();
      const { handleGetDataset } = await import("./get-dataset-BEVNXQNF.js");
      return {
        content: [{ type: "text", text: await handleGetDataset(params) }]
      };
    }
  );
  server.tool(
    "platform_create_dataset",
    "Create a new dataset on the LangWatch platform.",
    createDatasetSchema.shape,
    async (params) => {
      const { requireApiKey: requireApiKey2 } = await import("./config.js");
      requireApiKey2();
      const { handleCreateDataset } = await import("./create-dataset-BVXPVVY2.js");
      return {
        content: [{ type: "text", text: await handleCreateDataset(params) }]
      };
    }
  );
  server.tool(
    "platform_update_dataset",
    "Update an existing dataset on the LangWatch platform (name and/or column types).",
    {
      slugOrId: z2.string().describe("The dataset slug or ID to update"),
      name: z2.string().optional().describe("Updated dataset name"),
      columnTypes: z2.array(datasetColumnDefinitionSchema).optional().describe("Updated column definitions")
    },
    async (params) => {
      const { requireApiKey: requireApiKey2 } = await import("./config.js");
      requireApiKey2();
      const { handleUpdateDataset } = await import("./update-dataset-R4MM6NNY.js");
      return {
        content: [{ type: "text", text: await handleUpdateDataset(params) }]
      };
    }
  );
  server.tool(
    "platform_delete_dataset",
    "Delete (archive) a dataset on the LangWatch platform.",
    {
      slugOrId: z2.string().describe("The dataset slug or ID to delete")
    },
    async (params) => {
      const { requireApiKey: requireApiKey2 } = await import("./config.js");
      requireApiKey2();
      const { handleDeleteDataset } = await import("./delete-dataset-SZAHFHHS.js");
      return {
        content: [{ type: "text", text: await handleDeleteDataset(params) }]
      };
    }
  );
  server.tool(
    "platform_list_dataset_records",
    "List records in a dataset on the LangWatch platform with pagination.",
    {
      slugOrId: z2.string().describe("The dataset slug or ID to list records from"),
      page: z2.number().int().min(1).optional().describe("Page number (default: 1)"),
      limit: z2.number().int().min(1).max(1e3).optional().describe("Records per page (default: 50, max: 1000)"),
      format: z2.enum(["digest", "json"]).optional().describe("Output format: 'digest' (default, AI-readable) or 'json' (full raw data)")
    },
    async (params) => {
      const { requireApiKey: requireApiKey2 } = await import("./config.js");
      requireApiKey2();
      const { handleListDatasetRecords } = await import("./list-dataset-records-GWWVOCII.js");
      return {
        content: [
          { type: "text", text: await handleListDatasetRecords(params) }
        ]
      };
    }
  );
  server.tool(
    "platform_create_dataset_records",
    "Add records to a dataset on the LangWatch platform in batch (max 1000 per call).",
    {
      slugOrId: z2.string().describe("The dataset slug or ID to add records to"),
      entries: z2.array(z2.record(z2.string(), z2.unknown())).min(1).max(1e3).describe("Array of record entries to create (key-value objects matching dataset columns)")
    },
    async (params) => {
      const { requireApiKey: requireApiKey2 } = await import("./config.js");
      requireApiKey2();
      const { handleCreateDatasetRecords } = await import("./create-dataset-records-S7VFIIMR.js");
      return {
        content: [
          { type: "text", text: await handleCreateDatasetRecords(params) }
        ]
      };
    }
  );
  server.tool(
    "platform_update_dataset_record",
    "Update a single record in a dataset on the LangWatch platform.",
    {
      slugOrId: z2.string().describe("The dataset slug or ID containing the record"),
      recordId: z2.string().describe("The record ID to update"),
      entry: z2.record(z2.string(), z2.unknown()).describe("Updated record entry (key-value object)")
    },
    async (params) => {
      const { requireApiKey: requireApiKey2 } = await import("./config.js");
      requireApiKey2();
      const { handleUpdateDatasetRecord } = await import("./update-dataset-record-FN4BL5P4.js");
      return {
        content: [
          { type: "text", text: await handleUpdateDatasetRecord(params) }
        ]
      };
    }
  );
  server.tool(
    "platform_delete_dataset_records",
    "Delete records from a dataset on the LangWatch platform by their IDs.",
    {
      slugOrId: z2.string().describe("The dataset slug or ID containing the records"),
      recordIds: z2.array(z2.string()).min(1).max(1e3).describe("Array of record IDs to delete")
    },
    async (params) => {
      const { requireApiKey: requireApiKey2 } = await import("./config.js");
      requireApiKey2();
      const { handleDeleteDatasetRecords } = await import("./delete-dataset-records-ISHKGEBH.js");
      return {
        content: [
          { type: "text", text: await handleDeleteDatasetRecords(params) }
        ]
      };
    }
  );
  server.tool(
    "platform_list_projects",
    "List all projects in your LangWatch organization. Requires an org-level API key.",
    {
      page: z2.number().int().positive().optional().describe("Page number (default: 1)"),
      limit: z2.number().int().positive().max(1e3).optional().describe("Results per page (default: 100)")
    },
    withToolLogging("platform_list_projects", async (params) => {
      requireApiKey();
      const { handleListProjects } = await import("./list-projects-OXJC2NW5.js");
      return {
        content: [{ type: "text", text: await handleListProjects(params) }]
      };
    })
  );
  server.tool(
    "platform_get_project",
    "Get details of a specific project by its ID.",
    {
      id: z2.string().describe("The project ID")
    },
    withToolLogging("platform_get_project", async (params) => {
      requireApiKey();
      const { handleGetProject } = await import("./get-project-H4V3GYRQ.js");
      return {
        content: [{ type: "text", text: await handleGetProject(params) }]
      };
    })
  );
  server.tool(
    "platform_create_project",
    `Create a new project in your LangWatch organization. Returns a one-time service API key for the project.

You must provide either teamId (to add the project to an existing team) or newTeamName (to create a new team for the project).`,
    {
      name: z2.string().describe("Project name"),
      language: z2.string().describe('Programming language (e.g. "python", "typescript")'),
      framework: z2.string().describe('Framework (e.g. "openai", "langchain", "custom")'),
      teamId: z2.string().optional().describe("ID of an existing team to add the project to"),
      newTeamName: z2.string().optional().describe("Name for a new team to create for this project")
    },
    withToolLogging("platform_create_project", async (params) => {
      requireApiKey();
      const { handleCreateProject } = await import("./create-project-BF7LMZH5.js");
      return {
        content: [{ type: "text", text: await handleCreateProject(params) }]
      };
    })
  );
  server.tool(
    "platform_update_project",
    "Update an existing project's name, language, framework, or PII redaction level.",
    {
      id: z2.string().describe("The project ID to update"),
      name: z2.string().optional().describe("New project name"),
      language: z2.string().optional().describe("New programming language"),
      framework: z2.string().optional().describe("New framework"),
      piiRedactionLevel: z2.enum(["STRICT", "ESSENTIAL", "DISABLED"]).optional().describe("PII redaction level")
    },
    withToolLogging("platform_update_project", async (params) => {
      requireApiKey();
      const { handleUpdateProject } = await import("./update-project-H53IHRBB.js");
      return {
        content: [{ type: "text", text: await handleUpdateProject(params) }]
      };
    })
  );
  server.tool(
    "platform_archive_project",
    "Archive (soft-delete) a project. The project can be restored later if needed.",
    {
      id: z2.string().describe("The project ID to archive")
    },
    withToolLogging("platform_archive_project", async (params) => {
      requireApiKey();
      const { handleArchiveProject } = await import("./archive-project-KAZFHR4A.js");
      return {
        content: [{ type: "text", text: await handleArchiveProject(params) }]
      };
    })
  );
  server.tool(
    "platform_list_api_keys",
    "List all API keys in your LangWatch organization. Shows key metadata, status (active/revoked/expired), and role bindings. API key tokens are never returned.",
    {},
    withToolLogging("platform_list_api_keys", async () => {
      requireApiKey();
      const { handleListApiKeys } = await import("./list-api-keys-JJI62KD2.js");
      return {
        content: [{ type: "text", text: await handleListApiKeys() }]
      };
    })
  );
  server.tool(
    "platform_create_api_key",
    `Create a new API key. Two types available:

- **personal**: Tied to a user, requires explicit role bindings (e.g. ADMIN on PROJECT:proj_123).
- **service**: Not tied to a user. Use projectIds for project-scoped service keys, or omit for org-wide access.

The token is returned once and cannot be retrieved again.`,
    {
      keyType: z2.enum(["personal", "service"]).describe("Key type: 'personal' (user-tied) or 'service' (headless)"),
      name: z2.string().describe("Key name (max 100 chars)"),
      description: z2.string().optional().describe("Key description (max 500 chars)"),
      expiresAt: z2.string().optional().describe("Expiration date (ISO string)"),
      bindings: z2.array(z2.object({
        role: z2.enum(["ADMIN", "MEMBER", "VIEWER"]).describe("Role"),
        scopeType: z2.enum(["ORGANIZATION", "TEAM", "PROJECT"]).describe("Scope type"),
        scopeId: z2.string().describe("Scope ID (org, team, or project ID)")
      })).optional().describe("Role bindings (required for personal keys)"),
      projectIds: z2.array(z2.string()).optional().describe("Project IDs for service keys (creates ADMIN bindings per project)")
    },
    withToolLogging("platform_create_api_key", async (params) => {
      requireApiKey();
      const { handleCreateApiKey } = await import("./create-api-key-23MXYC2L.js");
      return {
        content: [{ type: "text", text: await handleCreateApiKey(params) }]
      };
    })
  );
  server.tool(
    "platform_revoke_api_key",
    "Revoke an API key. Once revoked, the key can no longer be used for authentication.",
    {
      id: z2.string().describe("The API key ID to revoke")
    },
    withToolLogging("platform_revoke_api_key", async (params) => {
      requireApiKey();
      const { handleRevokeApiKey } = await import("./revoke-api-key-TONB4ADQ.js");
      return {
        content: [{ type: "text", text: await handleRevokeApiKey(params) }]
      };
    })
  );
}

export {
  createMcpServer
};
//# sourceMappingURL=chunk-HRFQAFPR.js.map