{"version":3,"file":"index.cjs","names":["QuerySpansRequest","GetSchemaRequest","GetSpansByIdsRequest","ListDistinctValuesRequest","AggregateSpansRequest","GetTraceSpansRequest","fs","services: DiscoveredService[]","path","DEFAULT_INSTRUCTIONS","createMcpServer","PACKAGE_NAME","PACKAGE_VERSION","StdioServerTransport"],"sources":["../src/apiClient.ts","../src/serviceDiscovery.ts","../src/index.ts"],"sourcesContent":["import type {\n  TuskDriftConfig,\n  SchemaResult,\n  QuerySpansInput,\n  GetSchemaInput,\n  ListDistinctValuesInput,\n  AggregateSpansInput,\n  GetTraceInput,\n  GetSpansByIdsInput,\n} from \"./types.js\";\nimport type { ServiceDiscoveryContext } from \"./serviceDiscovery.js\";\nimport type {\n  DriftDataProvider,\n  QuerySpansResult,\n  ListDistinctValuesResult,\n  AggregateSpansResult,\n  GetTraceResult,\n  GetSpansByIdsResult,\n} from \"./provider.js\";\nimport {\n  AggregateSpansRequest,\n  GetSchemaRequest,\n  GetSpansByIdsRequest,\n  GetTraceSpansRequest,\n  ListDistinctValuesRequest,\n  QuerySpansRequest,\n} from \"@use-tusk/drift-schemas/query/span_query\";\n\nconst PROTO_JSON_OPTIONS = { enumAsInteger: true } as const;\n\ntype QuerySpansApiResponse = {\n  spans: QuerySpansResult[\"spans\"];\n  hasMore: boolean;\n  total?: number;\n  totalCount?: number;\n};\n\n/**\n * HTTP client for communicating with the Tusk Drift API.\n * Implements DriftDataProvider for use with the MCP server.\n * Supports multi-service queries via ServiceDiscoveryContext.\n */\nexport class TuskDriftApiClient implements DriftDataProvider {\n  private readonly baseUrl: string;\n  private readonly apiToken: string;\n  private serviceContext?: ServiceDiscoveryContext;\n\n  constructor(config: TuskDriftConfig) {\n    this.baseUrl = config.apiBaseUrl.replace(/\\/$/, \"\");\n    this.apiToken = config.apiToken;\n  }\n\n  /**\n   * Set the service discovery context for resolving service IDs.\n   */\n  setServiceContext(context: ServiceDiscoveryContext): void {\n    this.serviceContext = context;\n  }\n\n  /**\n   * Resolve the service ID to use for a request.\n   * Uses the provided ID, or falls back to the service context.\n   */\n  private resolveServiceId(providedServiceId?: string): string {\n    if (this.serviceContext) {\n      return this.serviceContext.resolveServiceId(providedServiceId);\n    }\n    if (providedServiceId) {\n      return providedServiceId;\n    }\n    throw new Error(\n      \"No service ID provided and no service context configured. \" +\n        \"Set TUSK_DRIFT_SERVICE_ID or ensure a .tusk/config.yaml exists.\"\n    );\n  }\n\n  private async request<T>(endpoint: string, body: unknown): Promise<T> {\n    const url = `${this.baseUrl}/api/drift/query${endpoint}`;\n\n    const response = await fetch(url, {\n      method: \"POST\",\n      headers: {\n        \"Content-Type\": \"application/json\",\n        \"x-api-key\": this.apiToken,\n      },\n      body: JSON.stringify(body),\n    });\n\n    if (!response.ok) {\n      const errorText = await response.text();\n      throw new Error(`API request failed (${response.status}): ${errorText}`);\n    }\n\n    return response.json() as Promise<T>;\n  }\n\n  /**\n   * Query span recordings with filters\n   */\n  async querySpans(input: QuerySpansInput): Promise<QuerySpansResult> {\n    const result = await this.request<QuerySpansApiResponse>(\n      \"/spans\",\n      QuerySpansRequest.toJson(\n        QuerySpansRequest.create({\n          ...input,\n          observableServiceId: this.resolveServiceId(input.observableServiceId || undefined),\n        }),\n        PROTO_JSON_OPTIONS\n      )\n    );\n\n    const total = result.total ?? result.totalCount;\n    if (total === undefined) {\n      throw new Error(\"API response for /api/drift/query/spans is missing total/totalCount\");\n    }\n\n    return {\n      spans: result.spans,\n      total,\n      hasMore: result.hasMore,\n    };\n  }\n\n  /**\n   * Get schema information for a specific instrumentation\n   */\n  async getSchema(input: GetSchemaInput): Promise<SchemaResult> {\n    return this.request(\n      \"/schema\",\n      GetSchemaRequest.toJson(\n        GetSchemaRequest.create({\n          ...input,\n          observableServiceId: this.resolveServiceId(input.observableServiceId || undefined),\n        }),\n        PROTO_JSON_OPTIONS\n      )\n    );\n  }\n\n  /**\n   * Get span recordings by IDs\n   */\n  async getSpansByIds(input: GetSpansByIdsInput): Promise<GetSpansByIdsResult> {\n    return this.request(\n      \"/spans-by-id\",\n      GetSpansByIdsRequest.toJson(\n        GetSpansByIdsRequest.create({\n          ...input,\n          observableServiceId: this.resolveServiceId(input.observableServiceId || undefined),\n        }),\n        PROTO_JSON_OPTIONS\n      )\n    );\n  }\n\n  /**\n   * List distinct values for a field\n   */\n  async listDistinctValues(input: ListDistinctValuesInput): Promise<ListDistinctValuesResult> {\n    const result = await this.request<{ values: ListDistinctValuesResult[\"values\"] }>(\n      \"/distinct\",\n      ListDistinctValuesRequest.toJson(\n        ListDistinctValuesRequest.create({\n          ...input,\n          observableServiceId: this.resolveServiceId(input.observableServiceId || undefined),\n        }),\n        PROTO_JSON_OPTIONS\n      )\n    );\n    return {\n      values: result.values,\n      field: input.field,\n    };\n  }\n\n  /**\n   * Aggregate spans with grouping and metrics\n   */\n  async aggregateSpans(input: AggregateSpansInput): Promise<AggregateSpansResult> {\n    const result = await this.request<{ results: AggregateSpansResult[\"results\"] }>(\n      \"/aggregate\",\n      AggregateSpansRequest.toJson(\n        AggregateSpansRequest.create({\n          ...input,\n          observableServiceId: this.resolveServiceId(input.observableServiceId || undefined),\n        }),\n        PROTO_JSON_OPTIONS\n      )\n    );\n    return { results: result.results };\n  }\n\n  /**\n   * Get all spans in a trace as a tree\n   */\n  async getTrace(input: GetTraceInput): Promise<GetTraceResult> {\n    return this.request(\n      \"/trace\",\n      GetTraceSpansRequest.toJson(\n        GetTraceSpansRequest.create({\n          ...input,\n          observableServiceId: this.resolveServiceId(input.observableServiceId || undefined),\n        }),\n        PROTO_JSON_OPTIONS\n      )\n    );\n  }\n}\n\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\n/**\n * Represents a discovered Tusk service from a .tusk/config.yaml file\n */\nexport interface DiscoveredService {\n  /** The service ID from the config */\n  id: string;\n  /** The service name from the config */\n  name: string;\n  /** Path to the .tusk/config.yaml file */\n  configPath: string;\n  /** Root directory containing the .tusk folder */\n  rootPath: string;\n}\n\n/**\n * Parse a .tusk/config.yaml file to extract service info.\n * Uses simple regex parsing to avoid YAML dependency.\n */\nfunction parseConfigYaml(configPath: string): { id?: string; name?: string } {\n  try {\n    const content = fs.readFileSync(configPath, \"utf-8\");\n\n    // Simple regex parsing for id and name under service:\n    // Looks for patterns like:\n    //   service:\n    //     id: \"xxx\"\n    //     name: \"yyy\"\n    const idMatch = content.match(\n      /service:\\s*\\n(?:[^\\n]*\\n)*?\\s*id:\\s*[\"']?([^\"'\\n]+)[\"']?/\n    );\n    const nameMatch = content.match(\n      /service:\\s*\\n(?:[^\\n]*\\n)*?\\s*name:\\s*[\"']?([^\"'\\n]+)[\"']?/\n    );\n\n    return {\n      id: idMatch?.[1]?.trim(),\n      name: nameMatch?.[1]?.trim(),\n    };\n  } catch {\n    return {};\n  }\n}\n\n/**\n * Recursively search for .tusk/config.yaml files starting from the given roots.\n * Searches up to maxDepth levels deep.\n */\nfunction findTuskConfigs(\n  roots: string[],\n  maxDepth: number = 3\n): DiscoveredService[] {\n  const services: DiscoveredService[] = [];\n  const visited = new Set<string>();\n\n  function searchDirectory(dir: string, depth: number): void {\n    if (depth > maxDepth || visited.has(dir)) {\n      return;\n    }\n    visited.add(dir);\n\n    const configPath = path.join(dir, \".tusk\", \"config.yaml\");\n\n    if (fs.existsSync(configPath)) {\n      const parsed = parseConfigYaml(configPath);\n      if (parsed.id) {\n        services.push({\n          id: parsed.id,\n          name: parsed.name || path.basename(dir),\n          configPath,\n          rootPath: dir,\n        });\n      }\n      // Don't search subdirectories if we found a config here\n      return;\n    }\n\n    // Search subdirectories\n    try {\n      const entries = fs.readdirSync(dir, { withFileTypes: true });\n      for (const entry of entries) {\n        if (\n          entry.isDirectory() &&\n          !entry.name.startsWith(\".\") &&\n          entry.name !== \"node_modules\"\n        ) {\n          searchDirectory(path.join(dir, entry.name), depth + 1);\n        }\n      }\n    } catch {\n      // Ignore permission errors\n    }\n  }\n\n  for (const root of roots) {\n    // Normalize the path and resolve symlinks\n    try {\n      const resolvedRoot = fs.realpathSync(root);\n      searchDirectory(resolvedRoot, 0);\n    } catch {\n      // If we can't resolve the path, try it directly\n      searchDirectory(root, 0);\n    }\n  }\n\n  return services;\n}\n\n/**\n * Service discovery context that manages discovered services\n * and provides the appropriate service ID for API calls.\n */\nexport class ServiceDiscoveryContext {\n  private discoveredServices: DiscoveredService[] = [];\n  private defaultServiceId?: string;\n\n  constructor(envServiceId?: string) {\n    this.defaultServiceId = envServiceId;\n  }\n\n  /**\n   * Discover services from the given workspace roots.\n   */\n  discoverFromRoots(roots: string[]): void {\n    this.discoveredServices = findTuskConfigs(roots);\n    console.error(\n      `Discovered ${this.discoveredServices.length} Tusk service(s):`\n    );\n    for (const service of this.discoveredServices) {\n      console.error(`  - ${service.name} (${service.id})`);\n    }\n  }\n\n  /**\n   * Get all discovered services.\n   */\n  getServices(): DiscoveredService[] {\n    return this.discoveredServices;\n  }\n\n  /**\n   * Get the service ID to use for an API call.\n   * Priority:\n   * 1. Explicitly provided serviceId\n   * 2. Environment variable default\n   * 3. Single discovered service (if only one)\n   * 4. Error if multiple discovered and none specified\n   */\n  resolveServiceId(providedServiceId?: string): string {\n    // 1. Explicit service ID\n    if (providedServiceId) {\n      return providedServiceId;\n    }\n\n    // 2. Environment variable default\n    if (this.defaultServiceId) {\n      return this.defaultServiceId;\n    }\n\n    // 3. Single discovered service\n    if (this.discoveredServices.length === 1) {\n      return this.discoveredServices[0].id;\n    }\n\n    // 4. Multiple or no services\n    if (this.discoveredServices.length === 0) {\n      throw new Error(\n        \"No Tusk service configured. Either set TUSK_DRIFT_SERVICE_ID \" +\n          \"environment variable or ensure a .tusk/config.yaml exists in your workspace.\"\n      );\n    }\n\n    // Multiple services found\n    const serviceList = this.discoveredServices\n      .map((s) => `  - \"${s.name}\" (id: ${s.id})`)\n      .join(\"\\n\");\n    throw new Error(\n      `Multiple Tusk services found. Please specify observableServiceId:\\n${serviceList}`\n    );\n  }\n\n  /**\n   * Check if we have any services available (discovered or default).\n   */\n  hasServices(): boolean {\n    return !!this.defaultServiceId || this.discoveredServices.length > 0;\n  }\n\n  /**\n   * Get instructions text about available services.\n   */\n  getServicesDescription(): string {\n    if (this.discoveredServices.length === 0) {\n      if (this.defaultServiceId) {\n        return `Using configured service: ${this.defaultServiceId}`;\n      }\n      return \"No services discovered.\";\n    }\n\n    if (this.discoveredServices.length === 1) {\n      const s = this.discoveredServices[0];\n      return `Using service: \"${s.name}\" (id: ${s.id}, path: ${s.rootPath})`;\n    }\n\n    const serviceList = this.discoveredServices\n      .map((s) => `- \"${s.name}\" (id: ${s.id}, path: ${s.rootPath})`)\n      .join(\"\\n\");\n    return `Multiple services available. Specify observableServiceId when querying:\\n${serviceList}`;\n  }\n}\n","#!/usr/bin/env node\n\nimport { realpathSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { TuskDriftApiClient } from \"./apiClient.js\";\nimport { ServiceDiscoveryContext } from \"./serviceDiscovery.js\";\nimport { createMcpServer, DEFAULT_INSTRUCTIONS, PACKAGE_NAME, PACKAGE_VERSION } from \"./server.js\";\nimport type { TuskDriftConfig } from \"./types.js\";\n\n// Re-export for library usage\nexport { createMcpServer, DEFAULT_INSTRUCTIONS, PACKAGE_NAME, PACKAGE_VERSION } from \"./server.js\";\nexport { TuskDriftApiClient } from \"./apiClient.js\";\nexport { ServiceDiscoveryContext } from \"./serviceDiscovery.js\";\nexport type {\n  DriftDataProvider,\n  DriftAccessControl,\n  CreateMcpServerOptions,\n  QuerySpansResult,\n  ListDistinctValuesResult,\n  AggregateSpansResult,\n  GetTraceResult,\n  GetSpansByIdsResult,\n} from \"./provider.js\";\nexport type {\n  TuskDriftConfig,\n  SpanRecording,\n  TraceSpan,\n  SchemaResult,\n  DistinctValue,\n  AggregationRow,\n  QuerySpansInput,\n  GetSchemaInput,\n  ListDistinctValuesInput,\n  AggregateSpansInput,\n  GetTraceInput,\n  GetSpansByIdsInput,\n} from \"./types.js\";\n\nconst DEFAULT_API_URL = \"https://api.usetusk.ai\";\n\n/**\n * Get the configuration from the environment variables.\n * `observableServiceId` is optional and can be discovered from workspace.\n *\n * @throws If required environment variables are not set.\n */\nfunction getConfig(): TuskDriftConfig {\n  const apiBaseUrl = process.env.TUSK_DRIFT_API_URL || DEFAULT_API_URL;\n  const apiToken = process.env.TUSK_API_KEY;\n  const observableServiceId = process.env.TUSK_DRIFT_SERVICE_ID;\n\n  if (!apiToken) {\n    throw new Error(\"TUSK_API_KEY environment variable is required\");\n  }\n\n  return {\n    apiBaseUrl,\n    apiToken,\n    observableServiceId,\n  };\n}\n\n/**\n * Generate instructions that include discovered services.\n */\nfunction generateInstructions(serviceContext: ServiceDiscoveryContext): string {\n  const servicesDescription = serviceContext.getServicesDescription();\n  return `${DEFAULT_INSTRUCTIONS}\\n\\n${servicesDescription}`;\n}\n\nfunction normalizePath(filePath: string): string {\n  try {\n    return realpathSync(filePath);\n  } catch {\n    return resolve(filePath);\n  }\n}\n\nfunction isExecutedDirectly(): boolean {\n  const entryPoint = process.argv[1];\n  if (!entryPoint) {\n    return false;\n  }\n\n  return normalizePath(fileURLToPath(import.meta.url)) === normalizePath(entryPoint);\n}\n\nexport async function main() {\n  const config = getConfig();\n  const client = new TuskDriftApiClient(config);\n\n  // Initialize service discovery with env var as default\n  const serviceContext = new ServiceDiscoveryContext(config.observableServiceId);\n\n  // Try to discover services from workspace roots\n  // These can be passed via TUSK_WORKSPACE_ROOTS env var (comma-separated)\n  // or we'll try current directory\n  const workspaceRoots = process.env.TUSK_WORKSPACE_ROOTS\n    ? process.env.TUSK_WORKSPACE_ROOTS.split(\",\").map((r) => r.trim())\n    : [process.cwd()];\n\n  serviceContext.discoverFromRoots(workspaceRoots);\n  client.setServiceContext(serviceContext);\n\n  if (!serviceContext.hasServices()) {\n    console.error(\n      \"Warning: No Tusk services found. Set TUSK_DRIFT_SERVICE_ID or ensure .tusk/config.yaml exists in workspace.\"\n    );\n  }\n\n  const server = createMcpServer({\n    provider: client,\n    instructions: generateInstructions(serviceContext),\n    name: PACKAGE_NAME,\n    version: PACKAGE_VERSION,\n  });\n\n  // Register resource for service discovery\n  server.registerResource(\n    \"services\",\n    \"tusk://services\",\n    {\n      mimeType: \"application/json\",\n      description: \"List of available Tusk Drift services that can be queried\",\n    },\n    async () => {\n      const services = serviceContext.getServices();\n      return {\n        contents: [\n          {\n            uri: \"tusk://services\",\n            text: JSON.stringify(\n              {\n                services: services.map((s) => ({\n                  id: s.id,\n                  name: s.name,\n                  rootPath: s.rootPath,\n                })),\n                defaultServiceId: config.observableServiceId,\n              },\n              null,\n              2\n            ),\n            mimeType: \"application/json\",\n          },\n        ],\n      };\n    }\n  );\n\n  const transport = new StdioServerTransport();\n  await server.connect(transport);\n\n  // Log to stderr (stdout is reserved for MCP comms)\n  console.error(\"Tusk Drift MCP server started\");\n  console.error(`API URL: ${config.apiBaseUrl}`);\n  console.error(serviceContext.getServicesDescription());\n}\n\nif (isExecutedDirectly()) {\n  main().catch((error) => {\n    console.error(\"Fatal error:\", error);\n    process.exit(1);\n  });\n}\n"],"mappings":"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"}