{"version":3,"sources":["../src/auth/oauthClientProvider.ts","../src/config/mcpConfig.ts","../src/index.ts","../src/auth/tokenAuth.ts","../src/auth/setupOAuth.ts","../src/debug.ts","../src/auth/discovery.ts","../src/auth/storage.ts","../src/auth/oauthFlow.ts","../src/auth/cli.ts","../src/mcp/clientFactory.ts","../src/mcp/response.ts","../src/assertions/validators/utils.ts","../src/assertions/validators/response.ts","../src/assertions/validators/schema.ts","../src/assertions/validators/text.ts","../src/assertions/validators/pattern.ts","../src/assertions/validators/error.ts","../src/assertions/validators/size.ts","../src/mcp/fixtures/mcpFixture.ts","../src/assertions/matchers/toMatchToolResponse.ts","../src/assertions/matchers/toMatchToolSchema.ts","../src/assertions/matchers/toContainToolText.ts","../src/assertions/matchers/toMatchToolPattern.ts","../src/assertions/matchers/toMatchToolSnapshot.ts","../src/assertions/matchers/toBeToolError.ts","../src/judge/claudeAgentJudge.ts","../src/judge/judgeClient.ts","../src/assertions/matchers/toPassToolJudge.ts","../src/assertions/matchers/toHaveToolResponseSize.ts","../src/assertions/matchers/toSatisfyToolPredicate.ts","../src/assertions/matchers/index.ts","../src/fixtures/mcp.ts","../src/evals/datasetTypes.ts","../src/evals/datasetLoader.ts","../src/evals/llmHost/adapter.ts","../src/evals/llmHost/retry.ts","../src/evals/llmHost/orchestrator.ts","../src/evals/llmHost/adapters/openai.ts","../src/evals/llmHost/adapters/anthropic.ts","../src/evals/llmHost/llmHostSimulation.ts","../src/evals/evalRunner.ts","../src/evals/llmHost/toolCallExpectation.ts","../src/spec/conformanceChecks.ts"],"names":["PlaywrightOAuthClientProvider","fs","path","z","createDebug","discoverAuthorizationServerMetadata","startAuthorization","chromium","exchangeAuthorization","loadOAuthState","oauth","path2","homedir","fs2","oauth2","DEFAULT_TIMEOUT_MS","http","Client","StdioClientTransport","StreamableHTTPClientTransport","extractText","truncateForDisplay","baseExpect","query","base","readFile","extractErrorMessage","result","pass"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * OAuth client provider implementation for MCP SDK\n *\n * Implements the MCP SDK's OAuthClientProvider interface using file-based storage\n * for integration with Playwright's auth state pattern.\n */\n\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { OAuthClientProvider } from '@modelcontextprotocol/sdk/client/auth.js';\nimport type {\n  OAuthClientMetadata,\n  OAuthClientInformationFull,\n  OAuthTokens,\n} from '@modelcontextprotocol/sdk/shared/auth.js';\nimport type { StoredOAuthState } from './types.js';\n\n/**\n * Configuration for the Playwright OAuth client provider\n */\nexport interface PlaywrightOAuthClientProviderConfig {\n  /**\n   * Path to the auth state file (e.g., playwright/.auth/oauth-state.json)\n   */\n  storagePath: string;\n\n  /**\n   * OAuth redirect URI for callback\n   */\n  redirectUri: string;\n\n  /**\n   * Client metadata for DCR or display\n   */\n  clientMetadata?: Partial<OAuthClientMetadata>;\n\n  /**\n   * Pre-registered client ID (if not using DCR)\n   */\n  clientId?: string;\n\n  /**\n   * Pre-registered client secret (if not using DCR)\n   */\n  clientSecret?: string;\n}\n\n/**\n * OAuth client provider that implements the MCP SDK's OAuthClientProvider interface\n *\n * Uses file-based storage for integration with Playwright's auth state pattern.\n * Auth state is persisted to disk so it can be reused across test runs.\n *\n * @example\n * ```typescript\n * const provider = new PlaywrightOAuthClientProvider({\n *   storagePath: 'playwright/.auth/oauth-state.json',\n *   redirectUri: 'http://localhost:3000/callback',\n * });\n *\n * const transport = new StreamableHTTPClientTransport(serverUrl, {\n *   authProvider: provider,\n * });\n * ```\n */\nexport class PlaywrightOAuthClientProvider implements OAuthClientProvider {\n  private readonly config: PlaywrightOAuthClientProviderConfig;\n  private cachedState: StoredOAuthState | null = null;\n  private stateParam: string | null = null;\n\n  constructor(config: PlaywrightOAuthClientProviderConfig) {\n    this.config = config;\n  }\n\n  /**\n   * The URL to redirect the user agent to after authorization\n   */\n  get redirectUrl(): string {\n    return this.config.redirectUri;\n  }\n\n  /**\n   * Metadata about this OAuth client\n   */\n  get clientMetadata(): OAuthClientMetadata {\n    return {\n      redirect_uris: [this.config.redirectUri],\n      token_endpoint_auth_method: this.config.clientSecret\n        ? 'client_secret_basic'\n        : 'none',\n      grant_types: ['authorization_code', 'refresh_token'],\n      response_types: ['code'],\n      client_name: '@mcp-testing/server-tester',\n      ...this.config.clientMetadata,\n    };\n  }\n\n  /**\n   * Returns an OAuth2 state parameter\n   */\n  state(): string {\n    if (!this.stateParam) {\n      this.stateParam = this.generateRandomString(32);\n    }\n    return this.stateParam;\n  }\n\n  /**\n   * Loads information about this OAuth client\n   */\n  async clientInformation(): Promise<OAuthClientInformationFull | undefined> {\n    // If we have a pre-registered client, return it\n    if (this.config.clientId) {\n      return {\n        client_id: this.config.clientId,\n        client_secret: this.config.clientSecret,\n        redirect_uris: [this.config.redirectUri],\n      };\n    }\n\n    // Otherwise, try to load from storage (DCR result)\n    const state = await this.loadState();\n    if (state?.clientInfo) {\n      return {\n        client_id: state.clientInfo.clientId,\n        client_secret: state.clientInfo.clientSecret,\n        client_id_issued_at: state.clientInfo.clientIdIssuedAt,\n        client_secret_expires_at: state.clientInfo.clientSecretExpiresAt,\n        redirect_uris: [this.config.redirectUri],\n      };\n    }\n\n    return undefined;\n  }\n\n  /**\n   * Saves client information from Dynamic Client Registration\n   */\n  async saveClientInformation(\n    clientInformation: OAuthClientInformationFull\n  ): Promise<void> {\n    const state = (await this.loadState()) ?? this.createEmptyState();\n    state.clientInfo = {\n      clientId: clientInformation.client_id,\n      clientSecret: clientInformation.client_secret,\n      clientIdIssuedAt: clientInformation.client_id_issued_at,\n      clientSecretExpiresAt: clientInformation.client_secret_expires_at,\n    };\n    await this.saveState(state);\n  }\n\n  /**\n   * Loads any existing OAuth tokens for the current session\n   */\n  async tokens(): Promise<OAuthTokens | undefined> {\n    const state = await this.loadState();\n    if (state?.tokens) {\n      return {\n        access_token: state.tokens.accessToken,\n        token_type: state.tokens.tokenType,\n        refresh_token: state.tokens.refreshToken,\n        expires_in: state.tokens.expiresAt\n          ? Math.floor((state.tokens.expiresAt - Date.now()) / 1000)\n          : undefined,\n      };\n    }\n    return undefined;\n  }\n\n  /**\n   * Stores new OAuth tokens for the current session\n   */\n  async saveTokens(tokens: OAuthTokens): Promise<void> {\n    const state = (await this.loadState()) ?? this.createEmptyState();\n    state.tokens = {\n      accessToken: tokens.access_token,\n      tokenType: tokens.token_type,\n      refreshToken: tokens.refresh_token,\n      expiresAt: tokens.expires_in\n        ? Date.now() + tokens.expires_in * 1000\n        : undefined,\n    };\n    await this.saveState(state);\n  }\n\n  /**\n   * Invoked to redirect the user agent to the given URL\n   *\n   * In a testing context, this is typically handled by Playwright automation.\n   * This implementation throws an error to signal that the caller needs to\n   * handle the redirect externally.\n   */\n  async redirectToAuthorization(authorizationUrl: URL): Promise<void> {\n    // In a test context, the authorization flow should be handled externally\n    // by Playwright automation (e.g., in globalSetup)\n    throw new Error(\n      `OAuth authorization required. Redirect to: ${authorizationUrl.toString()}\\n` +\n        'In a testing context, use performOAuthSetup() in your Playwright globalSetup ' +\n        'to complete the OAuth flow before running tests.'\n    );\n  }\n\n  /**\n   * Saves a PKCE code verifier for the current session\n   */\n  async saveCodeVerifier(codeVerifier: string): Promise<void> {\n    const state = (await this.loadState()) ?? this.createEmptyState();\n    state.codeVerifier = codeVerifier;\n    await this.saveState(state);\n  }\n\n  /**\n   * Loads the PKCE code verifier for the current session\n   */\n  async codeVerifier(): Promise<string> {\n    const state = await this.loadState();\n    if (!state?.codeVerifier) {\n      throw new Error('No code verifier found in auth state');\n    }\n    return state.codeVerifier;\n  }\n\n  /**\n   * Invalidates the specified credentials\n   */\n  async invalidateCredentials(\n    scope: 'all' | 'client' | 'tokens' | 'verifier'\n  ): Promise<void> {\n    const state = await this.loadState();\n    if (!state) {\n      return;\n    }\n\n    switch (scope) {\n      case 'all':\n        await this.deleteState();\n        break;\n      case 'client':\n        delete state.clientInfo;\n        await this.saveState(state);\n        break;\n      case 'tokens':\n        delete state.tokens;\n        await this.saveState(state);\n        break;\n      case 'verifier':\n        delete state.codeVerifier;\n        await this.saveState(state);\n        break;\n    }\n  }\n\n  // ---- Private helper methods ----\n\n  private async loadState(): Promise<StoredOAuthState | null> {\n    if (this.cachedState) {\n      return this.cachedState;\n    }\n\n    try {\n      const content = await fs.readFile(this.config.storagePath, 'utf-8');\n      this.cachedState = JSON.parse(content) as StoredOAuthState;\n      return this.cachedState;\n    } catch (error) {\n      if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n        return null;\n      }\n      throw error;\n    }\n  }\n\n  private async saveState(state: StoredOAuthState): Promise<void> {\n    state.savedAt = Date.now();\n    this.cachedState = state;\n\n    // Ensure directory exists\n    const dir = path.dirname(this.config.storagePath);\n    await fs.mkdir(dir, { recursive: true });\n\n    await fs.writeFile(\n      this.config.storagePath,\n      JSON.stringify(state, null, 2),\n      'utf-8'\n    );\n  }\n\n  private async deleteState(): Promise<void> {\n    this.cachedState = null;\n    try {\n      await fs.unlink(this.config.storagePath);\n    } catch (error) {\n      if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {\n        throw error;\n      }\n    }\n  }\n\n  private createEmptyState(): StoredOAuthState {\n    return {\n      savedAt: Date.now(),\n    };\n  }\n\n  private generateRandomString(length: number): string {\n    const chars =\n      'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n    let result = '';\n    const randomValues = new Uint8Array(length);\n    crypto.getRandomValues(randomValues);\n    for (let i = 0; i < length; i++) {\n      const randomValue = randomValues[i] ?? 0;\n      result += chars[randomValue % chars.length];\n    }\n    return result;\n  }\n}\n\n/**\n * Loads OAuth state from a single file (Playwright auth pattern)\n *\n * This function reads from Playwright's single-file auth state format,\n * typically created by `performOAuthSetup` in globalSetup.\n *\n * **Note:** This does NOT work with tokens stored by the CLI (`mcp-test login`).\n * For CLI-stored tokens, use `loadTokens(serverUrl)` instead.\n *\n * @param storagePath - Path to the auth state file (e.g., 'playwright/.auth/oauth-state.json')\n * @returns The stored OAuth state, or null if not found\n *\n * @example\n * ```typescript\n * // Load Playwright auth state\n * const state = await loadOAuthState('playwright/.auth/oauth-state.json');\n * ```\n */\nexport async function loadOAuthState(\n  storagePath: string\n): Promise<StoredOAuthState | null> {\n  try {\n    const content = await fs.readFile(storagePath, 'utf-8');\n    return JSON.parse(content) as StoredOAuthState;\n  } catch (error) {\n    if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n      return null;\n    }\n    throw error;\n  }\n}\n\n/**\n * Saves OAuth state to a single file (Playwright auth pattern)\n *\n * This function writes to Playwright's single-file auth state format.\n * Used by `performOAuthSetup` in globalSetup.\n *\n * **Note:** This does NOT work with the CLI storage format (`mcp-test login`).\n * For programmatic token injection compatible with CLI, use `injectTokens(serverUrl, tokens)`.\n *\n * @param storagePath - Path to the auth state file (e.g., 'playwright/.auth/oauth-state.json')\n * @param state - The OAuth state to save\n *\n * @example\n * ```typescript\n * // Save Playwright auth state\n * await saveOAuthState('playwright/.auth/oauth-state.json', {\n *   tokens: { accessToken: '...', tokenType: 'Bearer' },\n *   savedAt: Date.now(),\n * });\n * ```\n */\nexport async function saveOAuthState(\n  storagePath: string,\n  state: StoredOAuthState\n): Promise<void> {\n  state.savedAt = Date.now();\n\n  // Ensure directory exists\n  const dir = path.dirname(storagePath);\n  await fs.mkdir(dir, { recursive: true });\n\n  await fs.writeFile(storagePath, JSON.stringify(state, null, 2), 'utf-8');\n}\n","import { z } from 'zod';\n\n/**\n * OAuth configuration for MCP authentication\n */\nexport interface MCPOAuthConfig {\n  /**\n   * OAuth authorization server metadata URL\n   * (e.g., https://auth.example.com/.well-known/oauth-authorization-server)\n   */\n  serverUrl: string;\n\n  /**\n   * Scopes to request during authorization\n   */\n  scopes?: Array<string>;\n\n  /**\n   * Resource indicator (RFC 8707, required by MCP 2025-06-18 spec)\n   */\n  resource?: string;\n\n  /**\n   * Path to Playwright auth state file\n   * (e.g., playwright/.auth/oauth-state.json)\n   */\n  authStatePath?: string;\n\n  /**\n   * Client ID (if pre-registered; otherwise uses Dynamic Client Registration)\n   */\n  clientId?: string;\n\n  /**\n   * Client secret (for confidential clients)\n   */\n  clientSecret?: string;\n\n  /**\n   * Redirect URI for OAuth callback\n   */\n  redirectUri?: string;\n}\n\n/**\n * Authentication configuration for MCP connections\n */\nexport interface MCPAuthConfig {\n  /**\n   * Pre-acquired access token (simplest authentication mode)\n   */\n  accessToken?: string;\n\n  /**\n   * Full OAuth configuration for browser-based authentication\n   */\n  oauth?: MCPOAuthConfig;\n}\n\n/**\n * MCP host capabilities that can be registered with the server\n */\nexport interface MCPHostCapabilities {\n  /**\n   * Sampling capabilities (for LLM sampling)\n   */\n  sampling?: Record<string, unknown>;\n\n  /**\n   * Roots capabilities (for file system roots)\n   */\n  roots?: {\n    /**\n     * Whether the client can notify the server when roots change\n     */\n    listChanged: boolean;\n  };\n}\n\n/**\n * Configuration for MCP client connection\n *\n * Supports both stdio (local) and HTTP (remote) transports\n */\nexport interface MCPConfig {\n  /**\n   * Transport type\n   */\n  transport: 'http' | 'stdio';\n\n  /**\n   * Server URL (required when transport === 'http')\n   */\n  serverUrl?: string;\n\n  /**\n   * HTTP headers (optional for http transport, e.g., Authorization)\n   */\n  headers?: Record<string, string>;\n\n  /**\n   * Command to execute (required when transport === 'stdio')\n   */\n  command?: string;\n\n  /**\n   * Command arguments (optional for stdio)\n   */\n  args?: Array<string>;\n\n  /**\n   * Working directory for the command (optional for stdio)\n   */\n  cwd?: string;\n\n  /**\n   * Host capabilities to register with the server\n   */\n  capabilities?: MCPHostCapabilities;\n\n  /**\n   * Connection timeout in milliseconds\n   */\n  connectTimeoutMs?: number;\n\n  /**\n   * Request timeout in milliseconds\n   */\n  requestTimeoutMs?: number;\n\n  /**\n   * Suppress stderr output from the server process (stdio only)\n   * When true, server stderr is ignored instead of inherited\n   */\n  quiet?: boolean;\n\n  /**\n   * Authentication configuration (optional for http transport)\n   */\n  auth?: MCPAuthConfig;\n}\n\n/**\n * Zod schema for MCPHostCapabilities\n */\nconst MCPHostCapabilitiesSchema = z.object({\n  sampling: z.record(z.unknown()).optional(),\n  roots: z\n    .object({\n      listChanged: z.boolean(),\n    })\n    .optional(),\n});\n\n/**\n * Zod schema for MCPOAuthConfig\n */\nconst MCPOAuthConfigSchema = z.object({\n  serverUrl: z.string().url('serverUrl must be a valid URL'),\n  scopes: z.array(z.string()).optional(),\n  resource: z.string().url().optional(),\n  authStatePath: z.string().optional(),\n  clientId: z.string().optional(),\n  clientSecret: z.string().optional(),\n  redirectUri: z.string().url().optional(),\n});\n\n/**\n * Zod schema for MCPAuthConfig\n */\nconst MCPAuthConfigSchema = z\n  .object({\n    accessToken: z.string().optional(),\n    oauth: MCPOAuthConfigSchema.optional(),\n  })\n  .refine(\n    (data) => !(data.accessToken && data.oauth),\n    'Cannot specify both accessToken and oauth configuration'\n  );\n\n/**\n * Zod schema for stdio transport config\n */\nconst StdioConfigSchema = z.object({\n  transport: z.literal('stdio'),\n  command: z.string().min(1, 'command is required for stdio transport'),\n  args: z.array(z.string()).optional(),\n  cwd: z.string().optional(),\n  capabilities: MCPHostCapabilitiesSchema.optional(),\n  connectTimeoutMs: z.number().positive().optional(),\n  requestTimeoutMs: z.number().positive().optional(),\n  quiet: z.boolean().optional(),\n});\n\n/**\n * Zod schema for HTTP transport config\n */\nconst HttpConfigSchema = z.object({\n  transport: z.literal('http'),\n  serverUrl: z.string().url('serverUrl must be a valid URL'),\n  headers: z.record(z.string()).optional(),\n  capabilities: MCPHostCapabilitiesSchema.optional(),\n  connectTimeoutMs: z.number().positive().optional(),\n  requestTimeoutMs: z.number().positive().optional(),\n  auth: MCPAuthConfigSchema.optional(),\n});\n\n/**\n * Union schema for MCPConfig (validates based on transport type)\n */\nexport const MCPConfigSchema = z.discriminatedUnion('transport', [\n  StdioConfigSchema,\n  HttpConfigSchema,\n]);\n\n/**\n * Validates an MCPConfig object\n *\n * @param config - The config to validate\n * @returns The validated config\n * @throws {z.ZodError} If validation fails\n */\nexport function validateMCPConfig(config: unknown): MCPConfig {\n  return MCPConfigSchema.parse(config);\n}\n\n/**\n * Type guard to check if a config is for stdio transport\n */\nexport function isStdioConfig(\n  config: MCPConfig\n): config is MCPConfig & { transport: 'stdio'; command: string } {\n  return config.transport === 'stdio' && typeof config.command === 'string';\n}\n\n/**\n * Type guard to check if a config is for HTTP transport\n */\nexport function isHttpConfig(\n  config: MCPConfig\n): config is MCPConfig & { transport: 'http'; serverUrl: string } {\n  return config.transport === 'http' && typeof config.serverUrl === 'string';\n}\n","/**\n * @mcp-testing/server-tester\n *\n * Playwright-based testing framework for MCP servers\n *\n * @packageDocumentation\n */\n\n// Config\nexport type {\n  MCPConfig,\n  MCPHostCapabilities,\n  MCPAuthConfig,\n  MCPOAuthConfig,\n} from './config/mcpConfig.js';\nexport {\n  MCPConfigSchema,\n  validateMCPConfig,\n  isStdioConfig,\n  isHttpConfig,\n} from './config/mcpConfig.js';\n\n// Auth\nexport type {\n  StoredTokens,\n  StoredClientInfo,\n  StoredOAuthState,\n  OAuthSetupConfig,\n  TokenResult,\n} from './auth/types.js';\nexport {\n  PlaywrightOAuthClientProvider,\n  type PlaywrightOAuthClientProviderConfig,\n} from './auth/oauthClientProvider.js';\nexport {\n  createTokenAuthHeaders,\n  validateAccessToken,\n  isTokenExpired,\n  isTokenExpiringSoon,\n} from './auth/tokenAuth.js';\nexport {\n  performOAuthSetup,\n  performOAuthSetupIfNeeded,\n} from './auth/setupOAuth.js';\n\n// Discovery (RFC 9728)\nexport {\n  discoverProtectedResource,\n  discoverAuthorizationServer,\n  DiscoveryError,\n  MCP_PROTOCOL_VERSION,\n  type ProtectedResourceMetadata,\n  type ProtectedResourceDiscoveryResult,\n} from './auth/discovery.js';\n\n// Token Storage\nexport {\n  loadTokens,\n  hasValidTokens,\n  injectTokens,\n  loadTokensFromEnv,\n  ENV_VAR_NAMES,\n  type StoredServerMetadata,\n} from './auth/storage.js';\n\n// CLI OAuth\nexport {\n  CLIOAuthClient,\n  type CLIOAuthClientConfig,\n  type CLIOAuthResult,\n} from './auth/cli.js';\n\n// MCP Client\nexport {\n  createMCPClientForConfig,\n  closeMCPClient,\n  type CreateMCPClientOptions,\n} from './mcp/clientFactory.js';\n\n// Response Normalization\nexport type { ContentBlock, NormalizedToolResponse } from './mcp/response.js';\nexport { normalizeToolResponse, extractText } from './mcp/response.js';\n\n// Assertions - Matchers (primary API)\n// The extended expect with MCP tool matchers is exported via fixtures\n// Use: import { expect } from '@mcp-testing/server-tester'\n\n// Assertions - Validators (for programmatic use)\nexport {\n  validateResponse,\n  validateSchema,\n  validateText,\n  validatePattern,\n  validateError,\n  validateSize,\n  getResponseSizeBytes,\n} from './assertions/validators/index.js';\n\nexport type {\n  ValidationResult,\n  TextValidatorOptions,\n  SizeValidatorOptions,\n  SchemaValidatorOptions,\n  PatternValidatorOptions,\n  SnapshotSanitizer,\n  BuiltInSanitizer,\n  RegexSanitizer,\n  FieldRemovalSanitizer,\n  SchemaRegistry,\n} from './assertions/validators/types.js';\n\nexport type {\n  JudgeMatcherOptions,\n  ToolPredicate,\n  PredicateResult,\n} from './assertions/matchers/types.js';\n\n// Fixtures\nexport type {\n  MCPFixtureApi,\n  MCPFixtureOptions,\n  AuthType,\n} from './mcp/fixtures/mcpFixture.js';\nexport { createMCPFixture } from './mcp/fixtures/mcpFixture.js';\nexport { test, expect } from './fixtures/mcp.js';\n\n// Canonical Types (single source of truth)\nexport type {\n  ResultSource,\n  ExpectationType,\n  ExpectationBreakdown,\n  ExpectationResultMap,\n} from './types/index.js';\n\n// Eval Dataset\nexport type {\n  EvalCase,\n  EvalDataset,\n  EvalExpectBlock,\n  SerializedEvalDataset,\n  EvalMode,\n} from './evals/datasetTypes.js';\nexport {\n  EvalCaseSchema,\n  EvalDatasetSchema,\n  validateEvalCase,\n  validateEvalDataset,\n} from './evals/datasetTypes.js';\n\n// Eval Loader\nexport type { LoadDatasetOptions } from './evals/datasetLoader.js';\nexport {\n  loadEvalDataset,\n  loadEvalDatasetFromObject,\n} from './evals/datasetLoader.js';\n\n// Eval Runner\nexport type {\n  EvalContext,\n  EvalExpectationResult,\n  EvalCaseResult,\n  EvalRunnerResult,\n  EvalRunnerOptions,\n} from './evals/evalRunner.js';\nexport { runEvalDataset, runEvalCase } from './evals/evalRunner.js';\n\n// LLM Host Simulation\nexport type {\n  LLMProvider,\n  LLMHostConfig,\n  LLMToolCall,\n  LLMHostSimulationResult,\n  LLMHostSimulator,\n  ExpectedToolCall,\n  ToolCallValidationResult,\n  ToolCallValidator,\n} from './evals/llmHost/index.js';\nexport {\n  simulateLLMHost,\n  isProviderAvailable,\n  getMissingDependencyMessage,\n  createToolCallValidator,\n} from './evals/llmHost/index.js';\n\n// Judge\nexport type {\n  JudgeConfig,\n  Judge,\n  JudgeResult,\n  UsageMetrics,\n  ProviderKind,\n} from './judge/judgeTypes.js';\nexport { createJudge } from './judge/judgeClient.js';\n\n// Conformance\nexport type {\n  MCPConformanceOptions,\n  MCPConformanceResult,\n  MCPConformanceCheck,\n  MCPConformanceRaw,\n} from './spec/conformanceChecks.js';\nexport { runConformanceChecks } from './spec/conformanceChecks.js';\n\n// Reporter\nexport type {\n  MCPEvalReporterConfig,\n  MCPEvalRunData,\n  MCPEvalHistoricalSummary,\n  MCPConformanceResultData,\n  MCPServerCapabilitiesData,\n  MCPEvalData,\n} from './reporters/types.js';\n","/**\n * Static token authentication utilities\n *\n * Simple utilities for pre-acquired token authentication\n */\n\n/**\n * Creates HTTP headers for static token authentication\n *\n * @param accessToken - The pre-acquired access token\n * @param tokenType - The token type (default: \"Bearer\")\n * @returns HTTP headers with Authorization header\n *\n * @example\n * ```typescript\n * const headers = createTokenAuthHeaders(process.env.MCP_ACCESS_TOKEN);\n * // { Authorization: 'Bearer eyJ...' }\n * ```\n */\nexport function createTokenAuthHeaders(\n  accessToken: string,\n  tokenType: string = 'Bearer'\n): Record<string, string> {\n  return {\n    Authorization: `${tokenType} ${accessToken}`,\n  };\n}\n\n/**\n * Validates that an access token is present and non-empty\n *\n * @param accessToken - The access token to validate\n * @throws Error if token is missing or empty\n */\nexport function validateAccessToken(accessToken: string | undefined): void {\n  if (!accessToken) {\n    throw new Error('Access token is required but was not provided');\n  }\n\n  if (accessToken.trim().length === 0) {\n    throw new Error('Access token cannot be empty');\n  }\n}\n\n/**\n * Checks if a token appears to be expired based on common JWT structure\n *\n * Note: This is a best-effort check and may not work for all token formats.\n * For reliable expiration checking, use the token's associated expiration time.\n *\n * @param accessToken - The access token to check\n * @returns true if the token appears to be expired, false otherwise\n */\nexport function isTokenExpired(accessToken: string): boolean {\n  try {\n    // Try to decode as JWT\n    const parts = accessToken.split('.');\n    if (parts.length !== 3) {\n      // Not a JWT, can't determine expiration\n      return false;\n    }\n\n    const payloadPart = parts[1];\n    if (!payloadPart) {\n      return false;\n    }\n\n    const payload = JSON.parse(\n      Buffer.from(payloadPart, 'base64url').toString('utf-8')\n    ) as Record<string, unknown>;\n\n    if (typeof payload.exp === 'number') {\n      // exp is in seconds, Date.now() is in milliseconds\n      return payload.exp * 1000 < Date.now();\n    }\n\n    return false;\n  } catch {\n    // If we can't parse the token, assume it's not expired\n    return false;\n  }\n}\n\n/**\n * Checks if a token will expire within the specified buffer time\n *\n * @param expiresAt - Token expiration timestamp in milliseconds\n * @param bufferMs - Buffer time in milliseconds (default: 60000 = 1 minute)\n * @returns true if the token will expire within the buffer time\n */\nexport function isTokenExpiringSoon(\n  expiresAt: number | undefined,\n  bufferMs: number = 60000\n): boolean {\n  if (expiresAt === undefined) {\n    return false;\n  }\n\n  return expiresAt - bufferMs < Date.now();\n}\n","/**\n * OAuth setup utility for Playwright globalSetup\n *\n * Performs the browser-based OAuth flow and saves the auth state\n * for reuse across tests following Playwright's auth state pattern.\n */\n\nimport { chromium, type Page } from '@playwright/test';\nimport {\n  discoverAuthorizationServerMetadata,\n  startAuthorization,\n  exchangeAuthorization,\n} from '@modelcontextprotocol/sdk/client/auth.js';\nimport type { OAuthSetupConfig, StoredOAuthState } from './types.js';\nimport { saveOAuthState } from './oauthClientProvider.js';\nimport { debugOAuth } from '../debug.js';\n\n/**\n * Default timeout for OAuth login flow (30 seconds)\n */\nconst DEFAULT_TIMEOUT_MS = 30000;\n\n/**\n * Default redirect URI for OAuth callback\n */\nconst DEFAULT_REDIRECT_URI = 'http://localhost:3000/oauth/callback';\n\n/**\n * Performs the OAuth authorization flow using Playwright browser automation\n *\n * This function is designed to be used in Playwright's globalSetup to\n * authenticate once before running tests. The resulting auth state is\n * saved to disk and reused across tests.\n *\n * @param config - OAuth setup configuration\n *\n * @example\n * ```typescript\n * // global-setup.ts\n * import { performOAuthSetup } from '@mcp-testing/server-tester';\n *\n * export default async function globalSetup() {\n *   await performOAuthSetup({\n *     authServerUrl: 'https://auth.example.com',\n *     scopes: ['mcp:read', 'mcp:write'],\n *     loginSelectors: {\n *       usernameInput: '#username',\n *       passwordInput: '#password',\n *       submitButton: 'button[type=\"submit\"]',\n *     },\n *     credentials: {\n *       username: process.env.TEST_USER!,\n *       password: process.env.TEST_PASSWORD!,\n *     },\n *     outputPath: 'playwright/.auth/oauth-state.json',\n *   });\n * }\n * ```\n */\nexport async function performOAuthSetup(\n  config: OAuthSetupConfig\n): Promise<void> {\n  const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n  const redirectUri = config.redirectUri ?? DEFAULT_REDIRECT_URI;\n\n  // 1. Discover OAuth authorization server metadata\n  const metadata = await discoverAuthorizationServerMetadata(\n    config.authServerUrl\n  );\n\n  if (!metadata) {\n    throw new Error(\n      `Could not discover OAuth metadata at ${config.authServerUrl}`\n    );\n  }\n\n  // 2. Build client information\n  const clientInformation = {\n    client_id: config.clientId ?? 'mcp-testing-client',\n    client_secret: config.clientSecret,\n  };\n\n  // 3. Start authorization flow (generates PKCE, builds auth URL)\n  const { authorizationUrl, codeVerifier } = await startAuthorization(\n    config.authServerUrl,\n    {\n      metadata,\n      clientInformation,\n      redirectUrl: redirectUri,\n      scope: config.scopes.join(' '),\n      resource: config.resource ? new URL(config.resource) : undefined,\n    }\n  );\n\n  // 4. Launch browser and complete login flow\n  const browser = await chromium.launch({\n    headless: process.env.OAUTH_DEBUG !== 'true',\n  });\n\n  try {\n    const context = await browser.newContext();\n    const page = await context.newPage();\n\n    // Set timeout for the entire flow\n    page.setDefaultTimeout(timeoutMs);\n\n    // Navigate to authorization URL\n    await page.goto(authorizationUrl.toString());\n\n    // Complete login form\n    await completeLoginForm(page, config);\n\n    // Wait for redirect with authorization code\n    await page.waitForURL(\n      (url) => url.href.startsWith(redirectUri) && url.searchParams.has('code'),\n      { timeout: timeoutMs }\n    );\n\n    // Extract authorization code from callback URL\n    const callbackUrl = new URL(page.url());\n    const code = callbackUrl.searchParams.get('code');\n    const error = callbackUrl.searchParams.get('error');\n\n    if (error) {\n      const errorDescription =\n        callbackUrl.searchParams.get('error_description');\n      throw new Error(\n        `OAuth authorization failed: ${error}${errorDescription ? ` - ${errorDescription}` : ''}`\n      );\n    }\n\n    if (!code) {\n      throw new Error('No authorization code in callback URL');\n    }\n\n    // 5. Exchange authorization code for tokens\n    const tokens = await exchangeAuthorization(config.authServerUrl, {\n      metadata,\n      clientInformation,\n      authorizationCode: code,\n      codeVerifier,\n      redirectUri,\n      resource: config.resource ? new URL(config.resource) : undefined,\n    });\n\n    // 6. Save auth state to disk\n    const state: StoredOAuthState = {\n      tokens: {\n        accessToken: tokens.access_token,\n        tokenType: tokens.token_type,\n        refreshToken: tokens.refresh_token,\n        expiresAt: tokens.expires_in\n          ? Date.now() + tokens.expires_in * 1000\n          : undefined,\n      },\n      clientInfo: config.clientId\n        ? {\n            clientId: config.clientId,\n            clientSecret: config.clientSecret,\n          }\n        : undefined,\n      codeVerifier,\n      savedAt: Date.now(),\n    };\n\n    await saveOAuthState(config.outputPath, state);\n\n    debugOAuth('Auth state saved to %s', config.outputPath);\n  } finally {\n    await browser.close();\n  }\n}\n\n/**\n * Completes the login form using the provided selectors\n */\nasync function completeLoginForm(\n  page: Page,\n  config: OAuthSetupConfig\n): Promise<void> {\n  const { loginSelectors, credentials } = config;\n\n  // Wait for and fill username\n  await page.waitForSelector(loginSelectors.usernameInput, {\n    state: 'visible',\n  });\n  await page.fill(loginSelectors.usernameInput, credentials.username);\n\n  // Wait for and fill password\n  await page.waitForSelector(loginSelectors.passwordInput, {\n    state: 'visible',\n  });\n  await page.fill(loginSelectors.passwordInput, credentials.password);\n\n  // Click submit button\n  await page.waitForSelector(loginSelectors.submitButton, {\n    state: 'visible',\n  });\n  await page.click(loginSelectors.submitButton);\n\n  // Handle consent button if present\n  if (loginSelectors.consentButton) {\n    try {\n      await page.waitForSelector(loginSelectors.consentButton, {\n        state: 'visible',\n        timeout: 5000,\n      });\n      await page.click(loginSelectors.consentButton);\n    } catch {\n      // Consent button may not appear if already consented\n    }\n  }\n}\n\n/**\n * Checks if OAuth state exists and contains valid tokens (Playwright auth pattern)\n *\n * This function checks Playwright's single-file auth state format,\n * typically created by `performOAuthSetup` in globalSetup.\n *\n * **Note:** This does NOT work with tokens stored by the CLI (`mcp-test login`).\n * For CLI-stored tokens, use `hasValidTokens(serverUrl)` instead.\n *\n * @param storagePath - Path to the auth state file (e.g., 'playwright/.auth/oauth-state.json')\n * @returns true if valid auth state exists\n *\n * @example\n * ```typescript\n * // Check Playwright auth state\n * if (await hasValidOAuthState('playwright/.auth/oauth-state.json')) {\n *   console.log('Auth state is valid, skipping OAuth setup');\n * }\n * ```\n */\nexport async function hasValidOAuthState(\n  storagePath: string\n): Promise<boolean> {\n  try {\n    const { loadOAuthState } = await import('./oauthClientProvider.js');\n    const state = await loadOAuthState(storagePath);\n\n    if (!state?.tokens?.accessToken) {\n      return false;\n    }\n\n    // Check if token is expired (with 1 minute buffer)\n    if (state.tokens.expiresAt) {\n      const bufferMs = 60000;\n      if (state.tokens.expiresAt - bufferMs < Date.now()) {\n        return false;\n      }\n    }\n\n    return true;\n  } catch {\n    return false;\n  }\n}\n\n/**\n * Performs OAuth setup only if valid state doesn't already exist\n *\n * Use this in globalSetup to avoid re-authenticating on every test run.\n *\n * @param config - OAuth setup configuration\n *\n * @example\n * ```typescript\n * // global-setup.ts\n * export default async function globalSetup() {\n *   await performOAuthSetupIfNeeded({\n *     authServerUrl: 'https://auth.example.com',\n *     scopes: ['mcp:read'],\n *     loginSelectors: { ... },\n *     credentials: { ... },\n *     outputPath: 'playwright/.auth/oauth-state.json',\n *   });\n * }\n * ```\n */\nexport async function performOAuthSetupIfNeeded(\n  config: OAuthSetupConfig\n): Promise<void> {\n  const hasValid = await hasValidOAuthState(config.outputPath);\n\n  if (hasValid) {\n    debugOAuth('Using existing auth state from %s', config.outputPath);\n    return;\n  }\n\n  debugOAuth('No valid auth state found, performing OAuth flow...');\n  await performOAuthSetup(config);\n}\n","/**\n * Debug logging utilities\n *\n * Uses the `debug` package for conditional logging.\n * Enable via DEBUG environment variable:\n *\n * @example\n * ```bash\n * # Enable all mcp-testing logs\n * DEBUG=mcp-testing:* npm test\n *\n * # Enable only client logs\n * DEBUG=mcp-testing:client npm test\n *\n * # Enable only OAuth logs\n * DEBUG=mcp-testing:oauth npm test\n * ```\n */\n\nimport createDebug from 'debug';\n\nconst NAMESPACE = 'mcp-testing';\n\n/**\n * Debug logger for MCP client operations\n */\nexport const debugClient = createDebug(`${NAMESPACE}:client`);\n\n/**\n * Debug logger for OAuth operations\n */\nexport const debugOAuth = createDebug(`${NAMESPACE}:oauth`);\n\n/**\n * Debug logger for eval operations\n */\nexport const debugEval = createDebug(`${NAMESPACE}:eval`);\n","/**\n * OAuth Protected Resource and Authorization Server discovery\n *\n * Implements RFC 9728 (OAuth Protected Resource Metadata) and\n * RFC 8414 (Authorization Server Metadata) for MCP servers.\n */\n\nimport * as oauth from 'oauth4webapi';\nimport type { AuthServerMetadata } from './oauthFlow.js';\n\n/**\n * MCP Protocol version header value\n */\nexport const MCP_PROTOCOL_VERSION = '2025-06-18';\n\n/**\n * Protected Resource Metadata (RFC 9728)\n */\nexport interface ProtectedResourceMetadata {\n  /**\n   * The protected resource URL\n   */\n  resource: string;\n\n  /**\n   * Array of authorization server URLs\n   */\n  authorization_servers?: Array<string>;\n\n  /**\n   * Scopes supported by the protected resource\n   */\n  scopes_supported?: Array<string>;\n\n  /**\n   * Bearer token formats supported\n   */\n  bearer_methods_supported?: Array<string>;\n\n  /**\n   * Resource documentation URL\n   */\n  resource_documentation?: string;\n\n  /**\n   * Resource signing algorithms\n   */\n  resource_signing_alg_values_supported?: Array<string>;\n}\n\n/**\n * Result of protected resource discovery\n */\nexport interface ProtectedResourceDiscoveryResult {\n  /**\n   * The discovered metadata\n   */\n  metadata: ProtectedResourceMetadata;\n\n  /**\n   * The URL where metadata was found\n   */\n  discoveryUrl: string;\n\n  /**\n   * Whether path-aware discovery was used (vs base discovery)\n   */\n  usedPathAwareDiscovery: boolean;\n}\n\n/**\n * Discovers protected resource metadata per RFC 9728\n *\n * Follows RFC 9728 Section 4.1 for path-aware discovery:\n * 1. First tries: {origin}/.well-known/oauth-protected-resource{pathname}\n * 2. Falls back to: {origin}/.well-known/oauth-protected-resource\n *\n * @param mcpServerUrl - The MCP server URL\n * @returns Protected resource discovery result\n * @throws Error if discovery fails completely\n *\n * @example\n * const result = await discoverProtectedResource('https://api.example.com/mcp/default');\n * console.log(result.metadata.authorization_servers);\n */\nexport async function discoverProtectedResource(\n  mcpServerUrl: string\n): Promise<ProtectedResourceDiscoveryResult> {\n  const url = new URL(mcpServerUrl);\n  const origin = url.origin;\n  const pathname = url.pathname;\n\n  // Try path-aware discovery first (RFC 9728 Section 4.1)\n  const pathAwareUrl = `${origin}/.well-known/oauth-protected-resource${pathname}`;\n\n  try {\n    const metadata = await fetchProtectedResourceMetadata(pathAwareUrl);\n    return {\n      metadata,\n      discoveryUrl: pathAwareUrl,\n      usedPathAwareDiscovery: true,\n    };\n  } catch (error) {\n    // If path-aware fails with 404, try base discovery\n    if (error instanceof DiscoveryError && error.status === 404) {\n      const baseUrl = `${origin}/.well-known/oauth-protected-resource`;\n\n      // This will throw if base discovery also fails\n      const metadata = await fetchProtectedResourceMetadata(baseUrl);\n      return {\n        metadata,\n        discoveryUrl: baseUrl,\n        usedPathAwareDiscovery: false,\n      };\n    }\n\n    // Non-404 error from path-aware discovery\n    throw error;\n  }\n}\n\n/**\n * Error thrown when discovery fails\n */\nexport class DiscoveryError extends Error {\n  constructor(\n    message: string,\n    public readonly status?: number,\n    public readonly url?: string\n  ) {\n    super(message);\n    this.name = 'DiscoveryError';\n  }\n}\n\n/**\n * Fetches protected resource metadata from a discovery URL\n */\nasync function fetchProtectedResourceMetadata(\n  discoveryUrl: string\n): Promise<ProtectedResourceMetadata> {\n  const response = await fetch(discoveryUrl, {\n    method: 'GET',\n    headers: {\n      Accept: 'application/json',\n      'MCP-Protocol-Version': MCP_PROTOCOL_VERSION,\n    },\n  });\n\n  if (!response.ok) {\n    throw new DiscoveryError(\n      `Protected resource discovery failed: ${response.status} ${response.statusText}`,\n      response.status,\n      discoveryUrl\n    );\n  }\n\n  const metadata = (await response.json()) as ProtectedResourceMetadata;\n\n  // Validate required field\n  if (!metadata.resource) {\n    throw new DiscoveryError(\n      'Invalid protected resource metadata: missing required \"resource\" field',\n      undefined,\n      discoveryUrl\n    );\n  }\n\n  return metadata;\n}\n\n/**\n * Discovers OAuth Authorization Server metadata per RFC 8414\n *\n * Wraps oauth4webapi's discovery with MCP-specific headers.\n *\n * @param authServerUrl - The authorization server URL\n * @returns Authorization server metadata\n * @throws Error if discovery fails\n *\n * @example\n * const authServer = await discoverAuthorizationServer('https://auth.example.com');\n * console.log(authServer.server.token_endpoint);\n */\nexport async function discoverAuthorizationServer(\n  authServerUrl: string\n): Promise<AuthServerMetadata> {\n  const issuer = new URL(authServerUrl);\n\n  // Use oauth4webapi for discovery with custom headers\n  const response = await oauth.discoveryRequest(issuer, {\n    algorithm: 'oauth2',\n    headers: new Headers({\n      'MCP-Protocol-Version': MCP_PROTOCOL_VERSION,\n    }),\n  });\n\n  const metadata = await oauth.processDiscoveryResponse(issuer, response);\n\n  return {\n    server: metadata,\n    issuer: authServerUrl,\n  };\n}\n","/**\n * OAuth token storage with environment variable support for CI/CD\n *\n * Provides file-based storage for OAuth state per MCP server, with support\n * for token injection via environment variables for automated testing.\n */\n\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { homedir } from 'node:os';\nimport type { StoredTokens, StoredClientInfo } from './types.js';\nimport type { AuthServerMetadata } from './oauthFlow.js';\nimport type { ProtectedResourceMetadata } from './discovery.js';\n\n/**\n * Combined server metadata (auth server + protected resource)\n */\nexport interface StoredServerMetadata {\n  /**\n   * Authorization server metadata\n   */\n  authServer: AuthServerMetadata;\n\n  /**\n   * Protected resource metadata\n   */\n  protectedResource: ProtectedResourceMetadata;\n\n  /**\n   * Timestamp when metadata was discovered\n   */\n  discoveredAt: number;\n}\n\n/**\n * Interface for OAuth storage operations\n */\nexport interface OAuthStorage {\n  /**\n   * Load combined server metadata\n   */\n  loadServerMetadata(): Promise<StoredServerMetadata | null>;\n\n  /**\n   * Save combined server metadata\n   */\n  saveServerMetadata(metadata: StoredServerMetadata): Promise<void>;\n\n  /**\n   * Load registered client information\n   */\n  loadClient(): Promise<StoredClientInfo | null>;\n\n  /**\n   * Save registered client information\n   */\n  saveClient(client: StoredClientInfo): Promise<void>;\n\n  /**\n   * Load stored tokens\n   */\n  loadTokens(): Promise<StoredTokens | null>;\n\n  /**\n   * Save tokens\n   */\n  saveTokens(tokens: StoredTokens): Promise<void>;\n\n  /**\n   * Delete stored tokens\n   */\n  deleteTokens(): Promise<void>;\n\n  /**\n   * Check if valid (non-expired) token exists\n   * @param bufferMs - Buffer time in milliseconds before expiration (default: 60000)\n   */\n  hasValidToken(bufferMs?: number): Promise<boolean>;\n}\n\n/**\n * Configuration for file-based OAuth storage\n */\nexport interface FileOAuthStorageConfig {\n  /**\n   * MCP server URL (used to generate storage key)\n   */\n  serverUrl: string;\n\n  /**\n   * Custom state directory (overrides default)\n   */\n  stateDir?: string;\n}\n\n/**\n * Environment variable names for CI/CD token injection\n */\nexport const ENV_VAR_NAMES = {\n  accessToken: 'MCP_ACCESS_TOKEN',\n  refreshToken: 'MCP_REFRESH_TOKEN',\n  tokenType: 'MCP_TOKEN_TYPE',\n  expiresAt: 'MCP_TOKEN_EXPIRES_AT',\n} as const;\n\n/**\n * Default buffer time before token expiration (60 seconds)\n */\nconst DEFAULT_EXPIRY_BUFFER_MS = 60_000;\n\n/**\n * Generates a filesystem-safe key from a server URL\n *\n * @param serverUrl - The MCP server URL\n * @returns A filesystem-safe key string\n *\n * @example\n * generateServerKey('https://api.example.com:8080/mcp')\n * // Returns: 'api.example.com_8080_mcp'\n */\nexport function generateServerKey(serverUrl: string): string {\n  const url = new URL(serverUrl);\n\n  // Start with hostname\n  let key = url.hostname;\n\n  // Add port if non-standard\n  if (url.port) {\n    key += `_${url.port}`;\n  }\n\n  // Add path, replacing slashes with underscores\n  if (url.pathname && url.pathname !== '/') {\n    const cleanPath = url.pathname\n      .replace(/^\\/+|\\/+$/g, '') // Remove leading/trailing slashes\n      .replace(/\\//g, '_'); // Replace remaining slashes with underscores\n    if (cleanPath) {\n      key += `_${cleanPath}`;\n    }\n  }\n\n  // Make filesystem-safe: replace any remaining problematic characters\n  return key.replace(/[^a-zA-Z0-9_.-]/g, '_');\n}\n\n/**\n * Gets the state directory for a server\n *\n * Default locations:\n * - Linux: $XDG_STATE_HOME/mcp-tests/{serverKey}/ or ~/.local/state/mcp-tests/{serverKey}/\n * - macOS: ~/.local/state/mcp-tests/{serverKey}/\n * - Windows: %LOCALAPPDATA%\\mcp-tests\\{serverKey}\\\n *\n * @param serverUrl - The MCP server URL\n * @param customDir - Optional custom base directory\n * @returns The state directory path\n */\nexport function getStateDir(serverUrl: string, customDir?: string): string {\n  const serverKey = generateServerKey(serverUrl);\n\n  if (customDir) {\n    return path.join(customDir, serverKey);\n  }\n\n  // Platform-specific defaults\n  if (process.platform === 'win32') {\n    const localAppData = process.env.LOCALAPPDATA;\n    if (localAppData) {\n      return path.join(localAppData, 'mcp-tests', serverKey);\n    }\n    // Fallback for Windows\n    return path.join(homedir(), 'AppData', 'Local', 'mcp-tests', serverKey);\n  }\n\n  // Linux: Honor XDG_STATE_HOME\n  if (process.platform === 'linux' && process.env.XDG_STATE_HOME) {\n    return path.join(process.env.XDG_STATE_HOME, 'mcp-tests', serverKey);\n  }\n\n  // Default for macOS and Linux\n  return path.join(homedir(), '.local', 'state', 'mcp-tests', serverKey);\n}\n\n/**\n * Get the base directory for all MCP token storage\n */\nexport function getBaseStateDir(): string {\n  if (process.platform === 'win32') {\n    const localAppData = process.env.LOCALAPPDATA;\n    if (localAppData) {\n      return path.join(localAppData, 'mcp-tests');\n    }\n    return path.join(homedir(), 'AppData', 'Local', 'mcp-tests');\n  }\n\n  if (process.platform === 'linux' && process.env.XDG_STATE_HOME) {\n    return path.join(process.env.XDG_STATE_HOME, 'mcp-tests');\n  }\n\n  return path.join(homedir(), '.local', 'state', 'mcp-tests');\n}\n\n/**\n * Known server info\n */\nexport interface KnownServer {\n  /** The server key (directory name) */\n  key: string;\n  /** Reconstructed URL (best effort) */\n  url: string;\n  /** Whether valid tokens exist */\n  hasTokens: boolean;\n}\n\n/**\n * List all known authenticated servers from the token storage directory\n *\n * @returns Array of known servers with their URLs and token status\n */\nexport async function listKnownServers(): Promise<KnownServer[]> {\n  const baseDir = getBaseStateDir();\n  const servers: KnownServer[] = [];\n\n  try {\n    const entries = await fs.readdir(baseDir, { withFileTypes: true });\n\n    for (const entry of entries) {\n      if (!entry.isDirectory()) continue;\n\n      const serverKey = entry.name;\n      const tokensPath = path.join(baseDir, serverKey, 'tokens.json');\n\n      let hasTokens = false;\n      try {\n        await fs.access(tokensPath);\n        hasTokens = true;\n      } catch {\n        // No tokens file\n      }\n\n      // Reconstruct URL from server key (best effort)\n      // Format: hostname_port_path or hostname_path\n      const parts = serverKey.split('_');\n      const hostname = parts[0];\n      const rest = parts.slice(1).join('/');\n      const url = `https://${hostname}/${rest}`;\n\n      servers.push({ key: serverKey, url, hasTokens });\n    }\n  } catch {\n    // Directory doesn't exist or not readable\n  }\n\n  return servers;\n}\n\n/**\n * Reads tokens from environment variables (for CI/CD)\n *\n * @returns StoredTokens if MCP_ACCESS_TOKEN is set, null otherwise\n */\nexport function loadTokensFromEnv(): StoredTokens | null {\n  const accessToken = process.env[ENV_VAR_NAMES.accessToken];\n\n  if (!accessToken) {\n    return null;\n  }\n\n  const expiresAtStr = process.env[ENV_VAR_NAMES.expiresAt];\n  const expiresAt = expiresAtStr ? parseInt(expiresAtStr, 10) : undefined;\n\n  return {\n    accessToken,\n    refreshToken: process.env[ENV_VAR_NAMES.refreshToken],\n    tokenType: process.env[ENV_VAR_NAMES.tokenType] ?? 'Bearer',\n    expiresAt: expiresAt && !isNaN(expiresAt) ? expiresAt : undefined,\n  };\n}\n\n/**\n * Programmatically inject tokens into storage (for CI/CD setup)\n *\n * @param serverUrl - The MCP server URL\n * @param tokens - The tokens to inject\n * @param stateDir - Optional custom state directory\n */\nexport async function injectTokens(\n  serverUrl: string,\n  tokens: StoredTokens,\n  stateDir?: string\n): Promise<void> {\n  const storage = createFileOAuthStorage({ serverUrl, stateDir });\n  await storage.saveTokens(tokens);\n}\n\n/**\n * Load stored OAuth tokens for an MCP server\n *\n * Reads tokens from the standard storage location for the given server URL.\n * Tokens are stored by `mcp-test login` or `injectTokens()`.\n *\n * @param serverUrl - The MCP server URL\n * @param stateDir - Optional custom state directory\n * @returns StoredTokens if found, null otherwise\n *\n * @example\n * ```typescript\n * // After running: npx mcp-test login https://api.example.com/mcp\n * const tokens = await loadTokens('https://api.example.com/mcp');\n * if (tokens) {\n *   console.log('Access token:', tokens.accessToken);\n * }\n * ```\n */\nexport async function loadTokens(\n  serverUrl: string,\n  stateDir?: string\n): Promise<StoredTokens | null> {\n  const storage = createFileOAuthStorage({ serverUrl, stateDir });\n  return storage.loadTokens();\n}\n\n/**\n * Check if valid OAuth tokens exist for an MCP server\n *\n * Returns true if tokens exist and are not expired (with buffer).\n * Use this to check if authentication is needed before making requests.\n *\n * @param serverUrl - The MCP server URL\n * @param options - Optional configuration\n * @param options.stateDir - Custom state directory\n * @param options.bufferMs - Buffer time before expiration (default: 60000ms)\n * @returns true if valid (non-expired) tokens exist\n *\n * @example\n * ```typescript\n * if (await hasValidTokens('https://api.example.com/mcp')) {\n *   // Use stored tokens\n *   const tokens = await loadTokens('https://api.example.com/mcp');\n * } else {\n *   console.log('Run: npx mcp-test login https://api.example.com/mcp');\n * }\n * ```\n */\nexport async function hasValidTokens(\n  serverUrl: string,\n  options?: { stateDir?: string; bufferMs?: number }\n): Promise<boolean> {\n  const storage = createFileOAuthStorage({\n    serverUrl,\n    stateDir: options?.stateDir,\n  });\n  return storage.hasValidToken(options?.bufferMs);\n}\n\n/**\n * Creates a file-based OAuth storage instance\n *\n * @param config - Storage configuration\n * @returns OAuthStorage instance\n */\nexport function createFileOAuthStorage(\n  config: FileOAuthStorageConfig\n): OAuthStorage {\n  return new FileOAuthStorage(config);\n}\n\n/**\n * File-based OAuth storage implementation\n */\nclass FileOAuthStorage implements OAuthStorage {\n  private readonly stateDir: string;\n\n  constructor(config: FileOAuthStorageConfig) {\n    this.stateDir = getStateDir(config.serverUrl, config.stateDir);\n  }\n\n  private get serverMetadataPath(): string {\n    return path.join(this.stateDir, 'server.json');\n  }\n\n  private get clientPath(): string {\n    return path.join(this.stateDir, 'client.json');\n  }\n\n  private get tokensPath(): string {\n    return path.join(this.stateDir, 'tokens.json');\n  }\n\n  async loadServerMetadata(): Promise<StoredServerMetadata | null> {\n    return this.loadFile<StoredServerMetadata>(this.serverMetadataPath);\n  }\n\n  async saveServerMetadata(metadata: StoredServerMetadata): Promise<void> {\n    await this.atomicWrite(this.serverMetadataPath, metadata);\n  }\n\n  async loadClient(): Promise<StoredClientInfo | null> {\n    return this.loadFile<StoredClientInfo>(this.clientPath);\n  }\n\n  async saveClient(client: StoredClientInfo): Promise<void> {\n    await this.atomicWrite(this.clientPath, client);\n  }\n\n  async loadTokens(): Promise<StoredTokens | null> {\n    return this.loadFile<StoredTokens>(this.tokensPath);\n  }\n\n  async saveTokens(tokens: StoredTokens): Promise<void> {\n    await this.atomicWrite(this.tokensPath, tokens);\n  }\n\n  async deleteTokens(): Promise<void> {\n    await this.deleteFile(this.tokensPath);\n  }\n\n  async hasValidToken(\n    bufferMs: number = DEFAULT_EXPIRY_BUFFER_MS\n  ): Promise<boolean> {\n    const tokens = await this.loadTokens();\n\n    if (!tokens?.accessToken) {\n      return false;\n    }\n\n    // If no expiration, assume valid\n    if (!tokens.expiresAt) {\n      return true;\n    }\n\n    // Check if token is expired (with buffer)\n    return tokens.expiresAt > Date.now() + bufferMs;\n  }\n\n  /**\n   * Load a JSON file, returning null if not found\n   */\n  private async loadFile<T>(filePath: string): Promise<T | null> {\n    try {\n      const content = await fs.readFile(filePath, 'utf-8');\n      return JSON.parse(content) as T;\n    } catch (error) {\n      if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n        return null;\n      }\n      throw error;\n    }\n  }\n\n  /**\n   * Write data atomically: write to .tmp file, then rename\n   * Files are created with 0o600 permissions (user read/write only)\n   */\n  private async atomicWrite(filePath: string, data: unknown): Promise<void> {\n    // Ensure directory exists with restrictive permissions\n    await fs.mkdir(this.stateDir, { recursive: true, mode: 0o700 });\n\n    const tmpPath = `${filePath}.tmp`;\n    const content = JSON.stringify(data, null, 2);\n\n    // Write to temp file with restrictive permissions (user read/write only)\n    await fs.writeFile(tmpPath, content, { encoding: 'utf-8', mode: 0o600 });\n\n    // Atomic rename\n    await fs.rename(tmpPath, filePath);\n  }\n\n  /**\n   * Delete a file, ignoring errors if the file doesn't exist\n   */\n  private async deleteFile(filePath: string): Promise<void> {\n    try {\n      await fs.unlink(filePath);\n    } catch (error) {\n      // Ignore ENOENT (file doesn't exist)\n      if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {\n        throw error;\n      }\n    }\n  }\n}\n","/**\n * OAuth flow utilities using oauth4webapi\n *\n * Implements OAuth 2.1 with PKCE as required by MCP specification\n */\n\nimport * as oauth from 'oauth4webapi';\nimport type { TokenResult } from './types.js';\n\n/**\n * Discovered OAuth authorization server metadata\n */\nexport interface AuthServerMetadata {\n  /**\n   * The oauth4webapi AuthorizationServer object\n   */\n  server: oauth.AuthorizationServer;\n\n  /**\n   * Issuer URL\n   */\n  issuer: string;\n}\n\n/**\n * PKCE code verifier and challenge pair\n */\nexport interface PKCEPair {\n  /**\n   * Random code verifier string\n   */\n  codeVerifier: string;\n\n  /**\n   * S256 hashed code challenge\n   */\n  codeChallenge: string;\n}\n\n/**\n * Configuration for building authorization URL\n */\nexport interface AuthorizationUrlConfig {\n  /**\n   * Authorization server metadata\n   */\n  authServer: AuthServerMetadata;\n\n  /**\n   * Client ID\n   */\n  clientId: string;\n\n  /**\n   * Redirect URI for callback\n   */\n  redirectUri: string;\n\n  /**\n   * Requested scopes\n   */\n  scopes: Array<string>;\n\n  /**\n   * PKCE code challenge\n   */\n  codeChallenge: string;\n\n  /**\n   * OAuth state parameter for CSRF protection\n   */\n  state: string;\n\n  /**\n   * Resource indicator (RFC 8707)\n   */\n  resource?: string;\n}\n\n/**\n * Configuration for token exchange\n */\nexport interface TokenExchangeConfig {\n  /**\n   * Authorization server metadata\n   */\n  authServer: AuthServerMetadata;\n\n  /**\n   * Client ID\n   */\n  clientId: string;\n\n  /**\n   * Client secret (for confidential clients)\n   */\n  clientSecret?: string;\n\n  /**\n   * Authorization code from callback\n   */\n  code: string;\n\n  /**\n   * OAuth state parameter for CSRF validation\n   */\n  state: string;\n\n  /**\n   * PKCE code verifier\n   */\n  codeVerifier: string;\n\n  /**\n   * Redirect URI used in authorization request\n   */\n  redirectUri: string;\n}\n\n/**\n * Configuration for token refresh\n */\nexport interface TokenRefreshConfig {\n  /**\n   * Authorization server metadata\n   */\n  authServer: AuthServerMetadata;\n\n  /**\n   * Client ID\n   */\n  clientId: string;\n\n  /**\n   * Client secret (for confidential clients)\n   */\n  clientSecret?: string;\n\n  /**\n   * Refresh token\n   */\n  refreshToken: string;\n}\n\n/**\n * Discovers OAuth authorization server metadata from a well-known URL\n *\n * @param issuerUrl - The authorization server URL (will append /.well-known/oauth-authorization-server)\n * @returns Authorization server metadata\n */\nexport async function discoverAuthServer(\n  issuerUrl: string\n): Promise<AuthServerMetadata> {\n  const issuer = new URL(issuerUrl);\n  const response = await oauth.discoveryRequest(issuer, {\n    algorithm: 'oauth2',\n  });\n\n  const metadata = await oauth.processDiscoveryResponse(issuer, response);\n\n  return {\n    server: metadata,\n    issuer: issuerUrl,\n  };\n}\n\n/**\n * Generates a PKCE code verifier and challenge pair\n *\n * Uses S256 challenge method as required by OAuth 2.1 and MCP specification\n *\n * @returns PKCE code verifier and challenge\n */\nexport async function generatePKCE(): Promise<PKCEPair> {\n  const codeVerifier = oauth.generateRandomCodeVerifier();\n  const codeChallenge = await oauth.calculatePKCECodeChallenge(codeVerifier);\n\n  return {\n    codeVerifier,\n    codeChallenge,\n  };\n}\n\n/**\n * Generates a random state parameter for CSRF protection\n *\n * @returns Random state string\n */\nexport function generateState(): string {\n  return oauth.generateRandomState();\n}\n\n/**\n * Builds the OAuth authorization URL for browser redirect\n *\n * @param config - Authorization URL configuration\n * @returns Authorization URL to redirect the user to\n */\nexport function buildAuthorizationUrl(config: AuthorizationUrlConfig): URL {\n  const authorizationEndpoint = config.authServer.server.authorization_endpoint;\n  if (!authorizationEndpoint) {\n    throw new Error(\n      'Authorization server does not have an authorization_endpoint'\n    );\n  }\n\n  const authorizationUrl = new URL(authorizationEndpoint);\n\n  authorizationUrl.searchParams.set('client_id', config.clientId);\n  authorizationUrl.searchParams.set('redirect_uri', config.redirectUri);\n  authorizationUrl.searchParams.set('response_type', 'code');\n  authorizationUrl.searchParams.set('scope', config.scopes.join(' '));\n  authorizationUrl.searchParams.set('code_challenge', config.codeChallenge);\n  authorizationUrl.searchParams.set('code_challenge_method', 'S256');\n  authorizationUrl.searchParams.set('state', config.state);\n\n  if (config.resource) {\n    authorizationUrl.searchParams.set('resource', config.resource);\n  }\n\n  return authorizationUrl;\n}\n\n/**\n * Exchanges an authorization code for tokens\n *\n * @param config - Token exchange configuration\n * @returns Token result\n */\nexport async function exchangeCodeForTokens(\n  config: TokenExchangeConfig\n): Promise<TokenResult> {\n  const client: oauth.Client = {\n    client_id: config.clientId,\n    token_endpoint_auth_method: config.clientSecret\n      ? 'client_secret_basic'\n      : 'none',\n  };\n\n  const clientAuth = config.clientSecret\n    ? oauth.ClientSecretBasic(config.clientSecret)\n    : oauth.None();\n\n  // Build callback URL with code and state for validation\n  const callbackUrl = new URL(config.redirectUri);\n  callbackUrl.searchParams.set('code', config.code);\n  callbackUrl.searchParams.set('state', config.state);\n\n  // Validate the auth response - oauth4webapi requires this before token exchange\n  // This throws on error, returns URLSearchParams on success\n  const validatedParams = oauth.validateAuthResponse(\n    config.authServer.server,\n    client,\n    callbackUrl,\n    config.state\n  );\n\n  const response = await oauth.authorizationCodeGrantRequest(\n    config.authServer.server,\n    client,\n    clientAuth,\n    validatedParams,\n    config.redirectUri,\n    config.codeVerifier\n  );\n\n  const result = await oauth.processAuthorizationCodeResponse(\n    config.authServer.server,\n    client,\n    response\n  );\n\n  return {\n    accessToken: result.access_token,\n    tokenType: result.token_type,\n    expiresIn: result.expires_in,\n    refreshToken: result.refresh_token,\n    scope: result.scope,\n  };\n}\n\n/**\n * Refreshes an access token using a refresh token\n *\n * @param config - Token refresh configuration\n * @returns New token result\n */\nexport async function refreshAccessToken(\n  config: TokenRefreshConfig\n): Promise<TokenResult> {\n  const client: oauth.Client = {\n    client_id: config.clientId,\n    token_endpoint_auth_method: config.clientSecret\n      ? 'client_secret_basic'\n      : 'none',\n  };\n\n  const clientAuth = config.clientSecret\n    ? oauth.ClientSecretBasic(config.clientSecret)\n    : oauth.None();\n\n  const response = await oauth.refreshTokenGrantRequest(\n    config.authServer.server,\n    client,\n    clientAuth,\n    config.refreshToken\n  );\n\n  // Handle non-OK responses that may not be JSON (oauth4webapi requires application/json)\n  if (!response.ok) {\n    const contentType = response.headers.get('content-type') ?? '';\n    let errorMessage = `Token refresh failed: ${response.status} ${response.statusText}`;\n\n    try {\n      if (contentType.includes('application/json')) {\n        // Try to extract OAuth error from JSON response\n        const errorBody = (await response.clone().json()) as {\n          error?: string;\n          error_description?: string;\n        };\n        if (errorBody.error) {\n          errorMessage = `Token refresh failed: ${errorBody.error}`;\n          if (errorBody.error_description) {\n            errorMessage += ` - ${errorBody.error_description}`;\n          }\n        }\n      } else {\n        // Non-JSON response (e.g., text/plain) - read the body as text\n        const textBody = await response.clone().text();\n        if (textBody) {\n          errorMessage = `Token refresh failed: ${response.status} - ${textBody}`;\n        }\n      }\n    } catch {\n      // If we can't parse the error body, use the status message\n    }\n\n    throw new Error(errorMessage);\n  }\n\n  const result = await oauth.processRefreshTokenResponse(\n    config.authServer.server,\n    client,\n    response\n  );\n\n  return {\n    accessToken: result.access_token,\n    tokenType: result.token_type,\n    expiresIn: result.expires_in,\n    refreshToken: result.refresh_token,\n    scope: result.scope,\n  };\n}\n\n/**\n * Validates the callback URL from OAuth redirect\n *\n * @param callbackUrl - The full callback URL with query parameters\n * @param expectedState - The state parameter sent in the authorization request\n * @returns The authorization code\n * @throws Error if validation fails\n */\nexport function validateCallback(\n  callbackUrl: URL,\n  expectedState: string\n): string {\n  const error = callbackUrl.searchParams.get('error');\n  if (error) {\n    const errorDescription = callbackUrl.searchParams.get('error_description');\n    throw new Error(\n      `OAuth error: ${error}${errorDescription ? ` - ${errorDescription}` : ''}`\n    );\n  }\n\n  const state = callbackUrl.searchParams.get('state');\n  if (state !== expectedState) {\n    throw new Error('OAuth state mismatch - possible CSRF attack');\n  }\n\n  const code = callbackUrl.searchParams.get('code');\n  if (!code) {\n    throw new Error('No authorization code in callback URL');\n  }\n\n  return code;\n}\n","/**\n * CLI OAuth client for command-line authentication flows\n *\n * Provides browser-based OAuth authentication for CLI environments,\n * with support for environment variable token injection for CI/CD.\n */\n\nimport * as http from 'node:http';\nimport type { AddressInfo, Socket } from 'node:net';\nimport createDebug from 'debug';\nimport {\n  generatePKCE,\n  generateState,\n  buildAuthorizationUrl,\n  exchangeCodeForTokens,\n  refreshAccessToken,\n  type AuthServerMetadata,\n} from './oauthFlow.js';\nimport {\n  discoverProtectedResource,\n  discoverAuthorizationServer,\n  MCP_PROTOCOL_VERSION,\n  type ProtectedResourceMetadata,\n} from './discovery.js';\nimport {\n  createFileOAuthStorage,\n  loadTokensFromEnv,\n  type OAuthStorage,\n  type StoredServerMetadata,\n} from './storage.js';\nimport type { StoredTokens, StoredClientInfo, TokenResult } from './types.js';\n\nconst debug = createDebug('mcp-testing:cli-oauth');\n\n/**\n * Configuration for CLI OAuth client\n */\nexport interface CLIOAuthClientConfig {\n  /**\n   * MCP server URL (for protected resource discovery)\n   */\n  mcpServerUrl: string;\n\n  /**\n   * Scopes to request (optional, uses discovered scopes if not provided)\n   */\n  scopes?: Array<string>;\n\n  /**\n   * Custom storage directory\n   */\n  stateDir?: string;\n\n  /**\n   * Pre-registered client ID (skips DCR if provided)\n   */\n  clientId?: string;\n\n  /**\n   * Pre-registered client secret\n   */\n  clientSecret?: string;\n\n  /**\n   * Preferred callback port (default: random available port)\n   */\n  callbackPort?: number;\n\n  /**\n   * Timeout for OAuth flow in milliseconds (default: 300000 = 5 min)\n   */\n  timeoutMs?: number;\n\n  /**\n   * Client name for DCR registration\n   */\n  clientName?: string;\n}\n\n/**\n * Result of CLI OAuth authentication\n */\nexport interface CLIOAuthResult {\n  /**\n   * Access token\n   */\n  accessToken: string;\n\n  /**\n   * Token type (typically \"Bearer\")\n   */\n  tokenType: string;\n\n  /**\n   * Expiration timestamp (Unix ms)\n   */\n  expiresAt?: number;\n\n  /**\n   * Whether token was refreshed vs newly acquired\n   */\n  refreshed: boolean;\n\n  /**\n   * Scopes that were requested (only set for new authentications)\n   */\n  requestedScopes?: string[];\n\n  /**\n   * Whether token came from environment variables\n   */\n  fromEnv: boolean;\n}\n\n/**\n * Default timeout for OAuth flow (5 minutes)\n */\nconst DEFAULT_TIMEOUT_MS = 300_000;\n\n/**\n * Default client name for DCR\n */\nconst DEFAULT_CLIENT_NAME = '@mcp-testing/server-tester';\n\n/**\n * Default TTL for cached server metadata (24 hours)\n * After this time, metadata will be re-discovered\n */\nconst DEFAULT_METADATA_TTL_MS = 24 * 60 * 60 * 1000;\n\n/**\n * CLI OAuth client for command-line authentication flows\n */\nexport class CLIOAuthClient {\n  private readonly config: CLIOAuthClientConfig;\n  private readonly storage: OAuthStorage;\n\n  constructor(config: CLIOAuthClientConfig) {\n    this.config = config;\n    this.storage = createFileOAuthStorage({\n      serverUrl: config.mcpServerUrl,\n      stateDir: config.stateDir,\n    });\n  }\n\n  /**\n   * Get a valid access token, authenticating if necessary\n   *\n   * Token resolution priority:\n   * 1. Check environment variables (for CI/CD)\n   * 2. Check file storage for cached tokens\n   * 3. Try to refresh if expired but refresh token exists\n   * 4. Run full OAuth flow if needed\n   */\n  async getAccessToken(): Promise<CLIOAuthResult> {\n    // 1. Check environment variables first (CI/CD support)\n    const envTokens = loadTokensFromEnv();\n    if (envTokens) {\n      debug('Using tokens from environment variables');\n      return {\n        accessToken: envTokens.accessToken,\n        tokenType: envTokens.tokenType,\n        expiresAt: envTokens.expiresAt,\n        refreshed: false,\n        fromEnv: true,\n      };\n    }\n\n    // 2. Check file storage for cached tokens\n    const storedTokens = await this.storage.loadTokens();\n\n    if (storedTokens?.accessToken) {\n      // Check if token is still valid\n      const isValid = await this.storage.hasValidToken();\n\n      if (isValid) {\n        debug('Using cached tokens from storage');\n        return {\n          accessToken: storedTokens.accessToken,\n          tokenType: storedTokens.tokenType,\n          expiresAt: storedTokens.expiresAt,\n          refreshed: false,\n          fromEnv: false,\n        };\n      }\n\n      // 3. Try to refresh if we have a refresh token\n      if (storedTokens.refreshToken) {\n        debug('Token expired, attempting refresh');\n        try {\n          const refreshedTokens = await this.refreshStoredToken(storedTokens);\n          return {\n            accessToken: refreshedTokens.accessToken,\n            tokenType: refreshedTokens.tokenType,\n            expiresAt: refreshedTokens.expiresAt,\n            refreshed: true,\n            fromEnv: false,\n          };\n        } catch (error) {\n          debug('Token refresh failed, will re-authenticate:', error);\n          // Fall through to full authentication\n        }\n      }\n    }\n\n    // 4. Run full OAuth flow\n    debug('Performing full OAuth authentication');\n    return this.authenticate();\n  }\n\n  /**\n   * Try to get a valid access token without triggering browser auth\n   *\n   * Returns null if no valid token is available (no stored tokens,\n   * expired without refresh token, or refresh failed). Unlike getAccessToken(),\n   * this will NOT open a browser for authentication.\n   *\n   * Use this for CLI commands that should prompt the user to run `login`\n   * instead of automatically starting the OAuth flow.\n   */\n  async tryGetAccessToken(): Promise<CLIOAuthResult | null> {\n    // 1. Check environment variables first (CI/CD support)\n    const envTokens = loadTokensFromEnv();\n    if (envTokens) {\n      debug('Using tokens from environment variables');\n      return {\n        accessToken: envTokens.accessToken,\n        tokenType: envTokens.tokenType,\n        expiresAt: envTokens.expiresAt,\n        refreshed: false,\n        fromEnv: true,\n      };\n    }\n\n    // 2. Check file storage for cached tokens\n    const storedTokens = await this.storage.loadTokens();\n\n    if (storedTokens?.accessToken) {\n      // Check if token is still valid\n      const isValid = await this.storage.hasValidToken();\n\n      if (isValid) {\n        debug('Using cached tokens from storage');\n        return {\n          accessToken: storedTokens.accessToken,\n          tokenType: storedTokens.tokenType,\n          expiresAt: storedTokens.expiresAt,\n          refreshed: false,\n          fromEnv: false,\n        };\n      }\n\n      // 3. Try to refresh if we have a refresh token\n      if (storedTokens.refreshToken) {\n        debug('Token expired, attempting refresh');\n        try {\n          const refreshedTokens = await this.refreshStoredToken(storedTokens);\n          return {\n            accessToken: refreshedTokens.accessToken,\n            tokenType: refreshedTokens.tokenType,\n            expiresAt: refreshedTokens.expiresAt,\n            refreshed: true,\n            fromEnv: false,\n          };\n        } catch (error) {\n          debug('Token refresh failed:', error);\n          // Return null - don't fall through to browser auth\n          return null;\n        }\n      }\n    }\n\n    // No valid token available - return null instead of opening browser\n    debug('No valid token available');\n    return null;\n  }\n\n  /**\n   * Force a new authentication flow\n   */\n  async authenticate(): Promise<CLIOAuthResult> {\n    // Discover servers\n    const { protectedResource, authServer } = await this.discoverServers();\n\n    // Get or register client\n    const client = await this.getOrRegisterClient(authServer);\n\n    // Perform OAuth flow\n    const { tokens, requestedScopes } = await this.performOAuthFlow(\n      authServer,\n      client,\n      protectedResource\n    );\n\n    return {\n      accessToken: tokens.accessToken,\n      tokenType: tokens.tokenType,\n      expiresAt: tokens.expiresAt,\n      refreshed: false,\n      fromEnv: false,\n      requestedScopes,\n    };\n  }\n\n  /**\n   * Check if stored credentials exist (may be expired)\n   */\n  async hasStoredCredentials(): Promise<boolean> {\n    const tokens = await this.storage.loadTokens();\n    return tokens?.accessToken !== undefined;\n  }\n\n  /**\n   * Clear stored credentials\n   */\n  async clearCredentials(): Promise<void> {\n    await this.storage.deleteTokens();\n    debug('Cleared stored credentials');\n  }\n\n  /**\n   * Discover protected resource and authorization server\n   */\n  private async discoverServers(): Promise<{\n    protectedResource: ProtectedResourceMetadata;\n    authServer: AuthServerMetadata;\n  }> {\n    // Check cached server metadata\n    const cachedMetadata = await this.storage.loadServerMetadata();\n    if (cachedMetadata) {\n      // Check if metadata is stale (older than TTL)\n      const age = Date.now() - cachedMetadata.discoveredAt;\n      if (age < DEFAULT_METADATA_TTL_MS) {\n        debug('Using cached server metadata (age: %dms)', age);\n        debug(\n          'Cached protected resource scopes: %O',\n          cachedMetadata.protectedResource.scopes_supported\n        );\n        debug(\n          'Cached auth server scopes: %O',\n          cachedMetadata.authServer.server.scopes_supported\n        );\n        return {\n          protectedResource: cachedMetadata.protectedResource,\n          authServer: cachedMetadata.authServer,\n        };\n      }\n      debug('Cached server metadata is stale (age: %dms), re-discovering', age);\n    }\n\n    // Discover protected resource\n    debug('Discovering protected resource:', this.config.mcpServerUrl);\n    const prResult = await discoverProtectedResource(this.config.mcpServerUrl);\n    debug('Found protected resource:', prResult.metadata.resource);\n    debug(\n      'Protected resource scopes_supported: %O',\n      prResult.metadata.scopes_supported\n    );\n\n    // Get authorization server URL\n    const authServerUrl = prResult.metadata.authorization_servers?.[0];\n    if (!authServerUrl) {\n      throw new Error(\n        'No authorization servers found in protected resource metadata'\n      );\n    }\n\n    // Discover authorization server\n    debug('Discovering authorization server:', authServerUrl);\n    const authServer = await discoverAuthorizationServer(authServerUrl);\n    debug('Found authorization server:', authServer.issuer);\n    debug(\n      'Auth server scopes_supported: %O',\n      authServer.server.scopes_supported\n    );\n\n    // Cache metadata\n    const metadata: StoredServerMetadata = {\n      authServer,\n      protectedResource: prResult.metadata,\n      discoveredAt: Date.now(),\n    };\n    await this.storage.saveServerMetadata(metadata);\n\n    return {\n      protectedResource: prResult.metadata,\n      authServer,\n    };\n  }\n\n  /**\n   * Get existing client or register new one via DCR\n   */\n  private async getOrRegisterClient(\n    authServer: AuthServerMetadata\n  ): Promise<StoredClientInfo> {\n    // Use pre-configured client if provided\n    if (this.config.clientId) {\n      debug('Using pre-configured client ID');\n      return {\n        clientId: this.config.clientId,\n        clientSecret: this.config.clientSecret,\n      };\n    }\n\n    // Check cached client\n    const cachedClient = await this.storage.loadClient();\n    if (cachedClient?.clientId) {\n      debug('Using cached client registration');\n      return cachedClient;\n    }\n\n    // Register new client via DCR\n    debug('Registering new client via DCR');\n    const client = await this.registerClient(authServer);\n    await this.storage.saveClient(client);\n\n    return client;\n  }\n\n  /**\n   * Register a new client via Dynamic Client Registration\n   */\n  private async registerClient(\n    authServer: AuthServerMetadata\n  ): Promise<StoredClientInfo> {\n    const registrationEndpoint = authServer.server.registration_endpoint;\n    if (!registrationEndpoint) {\n      throw new Error(\n        'Authorization server does not support Dynamic Client Registration. ' +\n          'Please provide a clientId in the configuration.'\n      );\n    }\n\n    // We'll use a placeholder redirect URI for now\n    // The actual port will be determined when we start the callback server\n    const redirectUri = 'http://127.0.0.1:0/callback';\n\n    const response = await fetch(registrationEndpoint, {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/json',\n        'MCP-Protocol-Version': MCP_PROTOCOL_VERSION,\n      },\n      body: JSON.stringify({\n        redirect_uris: [redirectUri],\n        token_endpoint_auth_method: 'none',\n        grant_types: ['authorization_code', 'refresh_token'],\n        response_types: ['code'],\n        client_name: this.config.clientName ?? DEFAULT_CLIENT_NAME,\n      }),\n    });\n\n    if (!response.ok) {\n      const errorText = await response.text();\n      throw new Error(\n        `Dynamic Client Registration failed: ${response.status} ${response.statusText}\\n${errorText}`\n      );\n    }\n\n    const data = (await response.json()) as {\n      client_id: string;\n      client_secret?: string;\n      client_id_issued_at?: number;\n      client_secret_expires_at?: number;\n    };\n\n    debug('Client registered:', data.client_id);\n\n    return {\n      clientId: data.client_id,\n      clientSecret: data.client_secret,\n      clientIdIssuedAt: data.client_id_issued_at,\n      clientSecretExpiresAt: data.client_secret_expires_at,\n    };\n  }\n\n  /**\n   * Perform the full OAuth authorization flow\n   */\n  private async performOAuthFlow(\n    authServer: AuthServerMetadata,\n    client: StoredClientInfo,\n    protectedResource: ProtectedResourceMetadata\n  ): Promise<{ tokens: StoredTokens; requestedScopes: string[] }> {\n    // Generate PKCE and state\n    const pkce = await generatePKCE();\n    const state = generateState();\n\n    // Start callback server\n    const { port, codePromise, close } = await this.startCallbackServer(state);\n    const redirectUri = `http://127.0.0.1:${port}/callback`;\n\n    try {\n      // Determine scopes: user-provided > protected resource > auth server > fallback\n      // Try multiple sources since not all servers advertise scopes in the same place\n      const requestedScopes = this.config.scopes ??\n        protectedResource.scopes_supported ??\n        authServer.server.scopes_supported ?? ['openid'];\n\n      debug('Scope resolution:');\n      debug('  - User config scopes: %O', this.config.scopes);\n      debug(\n        '  - Protected resource scopes_supported: %O',\n        protectedResource.scopes_supported\n      );\n      debug(\n        '  - Auth server scopes_supported: %O',\n        authServer.server.scopes_supported\n      );\n      debug('  - Final requested scopes: %O', requestedScopes);\n\n      const authUrl = buildAuthorizationUrl({\n        authServer,\n        clientId: client.clientId,\n        redirectUri,\n        scopes: requestedScopes,\n        codeChallenge: pkce.codeChallenge,\n        state,\n        resource: protectedResource.resource,\n      });\n\n      debug('Authorization URL: %s', authUrl.toString());\n      debug('Authorization URL params:');\n      debug('  - client_id: %s', authUrl.searchParams.get('client_id'));\n      debug('  - redirect_uri: %s', authUrl.searchParams.get('redirect_uri'));\n      debug('  - scope: %s', authUrl.searchParams.get('scope'));\n      debug('  - resource: %s', authUrl.searchParams.get('resource'));\n\n      // Open browser or print URL\n      await this.openBrowserOrPrintUrl(authUrl);\n\n      // Wait for callback\n      debug('Waiting for OAuth callback...');\n      const code = await codePromise;\n      debug('Received authorization code');\n\n      // Exchange code for tokens\n      const tokenResult = await exchangeCodeForTokens({\n        authServer,\n        clientId: client.clientId,\n        clientSecret: client.clientSecret,\n        code,\n        state,\n        codeVerifier: pkce.codeVerifier,\n        redirectUri,\n      });\n\n      // Store tokens with the client ID used to obtain them\n      const tokens = this.tokenResultToStoredTokens(\n        tokenResult,\n        client.clientId\n      );\n      await this.storage.saveTokens(tokens);\n\n      return { tokens, requestedScopes };\n    } finally {\n      // Clean up callback server and all connections\n      close();\n    }\n  }\n\n  /**\n   * Refresh an expired token\n   *\n   * Uses the clientId stored with the tokens (if available) to ensure\n   * the refresh request uses the same client that obtained the original tokens.\n   * This is important because refresh tokens are bound to the client_id.\n   */\n  private async refreshStoredToken(\n    storedTokens: StoredTokens\n  ): Promise<StoredTokens> {\n    if (!storedTokens.refreshToken) {\n      throw new Error('No refresh token available');\n    }\n\n    // Get cached server metadata\n    const metadata = await this.storage.loadServerMetadata();\n    if (!metadata) {\n      throw new Error('No cached server metadata for refresh');\n    }\n\n    // Determine which client credentials to use for refresh.\n    // Priority: tokens.clientId > stored client.json > error\n    let clientId: string;\n    let clientSecret: string | undefined;\n\n    if (storedTokens.clientId) {\n      // Use the client ID that was used to obtain these tokens\n      debug('Using clientId from stored tokens for refresh');\n      clientId = storedTokens.clientId;\n\n      // Try to get the client secret from stored client info if it matches\n      const storedClient = await this.storage.loadClient();\n      if (storedClient?.clientId === clientId) {\n        clientSecret = storedClient.clientSecret;\n      }\n    } else {\n      // Legacy tokens without clientId - fall back to stored client\n      debug(\n        'No clientId in stored tokens, falling back to stored client (legacy behavior)'\n      );\n      const client = await this.getOrRegisterClient(metadata.authServer);\n      clientId = client.clientId;\n      clientSecret = client.clientSecret;\n    }\n\n    // Refresh token\n    const tokenResult = await refreshAccessToken({\n      authServer: metadata.authServer,\n      clientId,\n      clientSecret,\n      refreshToken: storedTokens.refreshToken,\n    });\n\n    // Store new tokens with the clientId that was used\n    const tokens = this.tokenResultToStoredTokens(tokenResult, clientId);\n    await this.storage.saveTokens(tokens);\n\n    return tokens;\n  }\n\n  /**\n   * Start local callback server\n   */\n  private async startCallbackServer(expectedState: string): Promise<{\n    port: number;\n    codePromise: Promise<string>;\n    close: () => void;\n  }> {\n    const timeoutMs = this.config.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\n    return new Promise((resolve, reject) => {\n      const server = http.createServer();\n\n      // Track active connections so we can force-close them\n      const connections = new Set<Socket>();\n      server.on('connection', (socket) => {\n        connections.add(socket);\n        socket.on('close', () => connections.delete(socket));\n      });\n\n      // Helper to force-close the server\n      const forceClose = () => {\n        for (const socket of connections) {\n          socket.destroy();\n        }\n        server.close();\n      };\n\n      let codeResolve: (code: string) => void;\n      let codeReject: (error: Error) => void;\n\n      const codePromise = new Promise<string>((res, rej) => {\n        codeResolve = res;\n        codeReject = rej;\n      });\n\n      // Set up timeout\n      const timeout = setTimeout(() => {\n        forceClose();\n        codeReject(new Error(`OAuth flow timed out after ${timeoutMs}ms`));\n      }, timeoutMs);\n\n      // Handle incoming requests\n      server.on('request', (req, res) => {\n        const url = new URL(\n          req.url ?? '/',\n          `http://127.0.0.1:${(server.address() as AddressInfo).port}`\n        );\n\n        if (url.pathname !== '/callback') {\n          res.writeHead(404);\n          res.end('Not Found');\n          return;\n        }\n\n        // Check for errors\n        const error = url.searchParams.get('error');\n        if (error) {\n          const errorDescription = url.searchParams.get('error_description');\n          clearTimeout(timeout);\n          res.writeHead(400, { 'Content-Type': 'text/html' });\n          res.end(this.errorHtml(error, errorDescription ?? undefined));\n          codeReject(\n            new Error(\n              `OAuth error: ${error}${errorDescription ? ` - ${errorDescription}` : ''}`\n            )\n          );\n          return;\n        }\n\n        // Validate state\n        const state = url.searchParams.get('state');\n        if (state !== expectedState) {\n          clearTimeout(timeout);\n          res.writeHead(400, { 'Content-Type': 'text/html' });\n          res.end(this.errorHtml('invalid_state', 'State parameter mismatch'));\n          codeReject(new Error('OAuth state mismatch - possible CSRF attack'));\n          return;\n        }\n\n        // Get authorization code\n        const code = url.searchParams.get('code');\n        if (!code) {\n          clearTimeout(timeout);\n          res.writeHead(400, { 'Content-Type': 'text/html' });\n          res.end(\n            this.errorHtml('missing_code', 'No authorization code received')\n          );\n          codeReject(new Error('No authorization code in callback'));\n          return;\n        }\n\n        // Success!\n        clearTimeout(timeout);\n        res.writeHead(200, { 'Content-Type': 'text/html' });\n        res.end(this.successHtml());\n        codeResolve(code);\n      });\n\n      // Listen on preferred port or random port\n      const preferredPort = this.config.callbackPort ?? 0;\n\n      server.listen(preferredPort, '127.0.0.1', () => {\n        const address = server.address() as AddressInfo;\n        debug('Callback server listening on port', address.port);\n        resolve({ port: address.port, codePromise, close: forceClose });\n      });\n\n      server.on('error', (err) => {\n        reject(err);\n      });\n    });\n  }\n\n  /**\n   * Open browser or print URL for headless environments\n   */\n  private async openBrowserOrPrintUrl(url: URL): Promise<void> {\n    if (isHeadless()) {\n      console.log('\\n' + '='.repeat(60));\n      console.log(\n        'Please open the following URL in your browser to authenticate:'\n      );\n      console.log('\\n' + url.toString() + '\\n');\n      console.log('='.repeat(60) + '\\n');\n      return;\n    }\n\n    try {\n      // Dynamic import of 'open' package\n      const open = await import('open');\n      await open.default(url.toString());\n      debug('Opened browser for authentication');\n    } catch (error) {\n      // If browser opening fails, fall back to printing URL\n      debug('Failed to open browser:', error);\n      console.log('\\nFailed to open browser automatically.');\n      console.log('Please open the following URL manually:\\n');\n      console.log(url.toString() + '\\n');\n    }\n  }\n\n  /**\n   * Convert TokenResult to StoredTokens\n   *\n   * @param result - Token result from exchange or refresh\n   * @param clientId - Client ID that was used to obtain these tokens\n   */\n  private tokenResultToStoredTokens(\n    result: TokenResult,\n    clientId: string\n  ): StoredTokens {\n    return {\n      accessToken: result.accessToken,\n      tokenType: result.tokenType,\n      refreshToken: result.refreshToken,\n      expiresAt: result.expiresIn\n        ? Date.now() + result.expiresIn * 1000\n        : undefined,\n      clientId,\n    };\n  }\n\n  /**\n   * HTML page for successful authentication\n   */\n  private successHtml(): string {\n    return `\n<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"UTF-8\">\n  <title>Authentication Successful</title>\n  <style>\n    body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n           display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0;\n           background: #f8fafc; }\n    .container { text-align: center; background: white; padding: 48px 64px; border-radius: 8px;\n                 border: 1px solid #e2e8f0; box-shadow: 0 1px 3px rgba(0,0,0,0.1); }\n    .icon { width: 48px; height: 48px; margin: 0 auto 24px; background: #dcfce7; border-radius: 50%;\n            display: flex; align-items: center; justify-content: center; }\n    .icon svg { width: 24px; height: 24px; color: #16a34a; }\n    h1 { color: #0f172a; margin: 0 0 8px 0; font-size: 20px; font-weight: 600; }\n    p { color: #64748b; margin: 0; font-size: 14px; }\n  </style>\n</head>\n<body>\n  <div class=\"container\">\n    <div class=\"icon\">\n      <svg fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n        <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 13l4 4L19 7\"/>\n      </svg>\n    </div>\n    <h1>Authentication Successful</h1>\n    <p>You can close this window and return to the terminal.</p>\n  </div>\n</body>\n</html>`;\n  }\n\n  /**\n   * HTML page for authentication error\n   */\n  private errorHtml(error: string, description?: string): string {\n    return `\n<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"UTF-8\">\n  <title>Authentication Failed</title>\n  <style>\n    body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n           display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0;\n           background: #f8fafc; }\n    .container { text-align: center; background: white; padding: 48px 64px; border-radius: 8px;\n                 border: 1px solid #e2e8f0; box-shadow: 0 1px 3px rgba(0,0,0,0.1); }\n    .icon { width: 48px; height: 48px; margin: 0 auto 24px; background: #fee2e2; border-radius: 50%;\n            display: flex; align-items: center; justify-content: center; }\n    .icon svg { width: 24px; height: 24px; color: #dc2626; }\n    h1 { color: #0f172a; margin: 0 0 8px 0; font-size: 20px; font-weight: 600; }\n    p { color: #64748b; margin: 0 0 8px 0; font-size: 14px; }\n    code { background: #f1f5f9; padding: 2px 8px; border-radius: 4px; color: #dc2626; font-size: 13px; }\n  </style>\n</head>\n<body>\n  <div class=\"container\">\n    <div class=\"icon\">\n      <svg fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n        <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\"/>\n      </svg>\n    </div>\n    <h1>Authentication Failed</h1>\n    <p>Error: <code>${escapeHtml(error)}</code></p>\n    ${description ? `<p>${escapeHtml(description)}</p>` : ''}\n  </div>\n</body>\n</html>`;\n  }\n}\n\n/**\n * Detect if running in a headless environment\n */\nfunction isHeadless(): boolean {\n  // CI environment\n  if (process.env.CI) {\n    return true;\n  }\n\n  // No TTY (piped input)\n  if (!process.stdin.isTTY) {\n    return true;\n  }\n\n  // Linux without DISPLAY (no X server)\n  if (\n    process.platform === 'linux' &&\n    !process.env.DISPLAY &&\n    !process.env.WAYLAND_DISPLAY\n  ) {\n    return true;\n  }\n\n  return false;\n}\n\n/**\n * Escape HTML special characters\n */\nfunction escapeHtml(text: string): string {\n  return text\n    .replace(/&/g, '&amp;')\n    .replace(/</g, '&lt;')\n    .replace(/>/g, '&gt;')\n    .replace(/\"/g, '&quot;')\n    .replace(/'/g, '&#039;');\n}\n","import { Client } from '@modelcontextprotocol/sdk/client/index.js';\nimport { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';\nimport { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';\nimport type { OAuthClientProvider } from '@modelcontextprotocol/sdk/client/auth.js';\nimport type { MCPConfig } from '../config/mcpConfig.js';\nimport {\n  validateMCPConfig,\n  isStdioConfig,\n  isHttpConfig,\n} from '../config/mcpConfig.js';\nimport { debugClient } from '../debug.js';\n\n/**\n * Options for creating an MCP client\n */\nexport interface CreateMCPClientOptions {\n  /**\n   * Client information (name and version)\n   */\n  clientInfo?: {\n    name?: string;\n    version?: string;\n  };\n\n  /**\n   * OAuth client provider for authentication\n   *\n   * When provided, the MCP SDK handles OAuth flow automatically.\n   * This takes precedence over static token auth in config.auth.accessToken.\n   */\n  authProvider?: OAuthClientProvider;\n}\n\n/**\n * Creates and connects an MCP client based on the provided configuration\n *\n * @param config - MCP configuration (will be validated)\n * @param options - Optional client options including auth provider\n * @returns Connected MCP Client instance\n * @throws {Error} If config is invalid or connection fails\n *\n * @example\n * // Stdio transport\n * const client = await createMCPClientForConfig({\n *   transport: 'stdio',\n *   command: 'node',\n *   args: ['server.js']\n * });\n *\n * @example\n * // HTTP transport with static token auth\n * const client = await createMCPClientForConfig({\n *   transport: 'http',\n *   serverUrl: 'http://localhost:3000/mcp',\n *   auth: { accessToken: 'your-token' }\n * });\n *\n * @example\n * // HTTP transport with OAuth provider\n * const client = await createMCPClientForConfig(\n *   { transport: 'http', serverUrl: 'http://localhost:3000/mcp' },\n *   { authProvider: myOAuthProvider }\n * );\n */\nexport async function createMCPClientForConfig(\n  config: MCPConfig,\n  options?: CreateMCPClientOptions\n): Promise<Client> {\n  // Validate config\n  const validatedConfig = validateMCPConfig(config);\n\n  // Create client with info\n  const client = new Client(\n    {\n      name: options?.clientInfo?.name ?? '@mcp-testing/server-tester',\n      version: options?.clientInfo?.version ?? '0.1.0',\n    },\n    {\n      capabilities: validatedConfig.capabilities ?? {},\n    }\n  );\n\n  // Create appropriate transport and connect\n  if (isStdioConfig(validatedConfig)) {\n    const transport = new StdioClientTransport({\n      command: validatedConfig.command,\n      args: validatedConfig.args ?? [],\n      ...(validatedConfig.cwd && { cwd: validatedConfig.cwd }),\n      // Suppress server stderr when quiet mode is enabled\n      ...(validatedConfig.quiet && { stderr: 'ignore' as const }),\n    });\n\n    debugClient('Connecting via stdio: %O', {\n      command: validatedConfig.command,\n      args: validatedConfig.args,\n      cwd: validatedConfig.cwd,\n    });\n\n    await client.connect(transport);\n  } else if (isHttpConfig(validatedConfig)) {\n    // Build headers, including static token auth if configured and no authProvider\n    const headers: Record<string, string> = { ...validatedConfig.headers };\n\n    // If using static token auth (no authProvider), add Authorization header\n    if (validatedConfig.auth?.accessToken && !options?.authProvider) {\n      headers.Authorization = `Bearer ${validatedConfig.auth.accessToken}`;\n    }\n\n    const transport = new StreamableHTTPClientTransport(\n      new URL(validatedConfig.serverUrl),\n      {\n        requestInit: Object.keys(headers).length > 0 ? { headers } : undefined,\n        // Pass auth provider for OAuth flow - MCP SDK handles it automatically\n        authProvider: options?.authProvider,\n      }\n    );\n\n    debugClient('Connecting via HTTP: %O', {\n      serverUrl: validatedConfig.serverUrl,\n      headers:\n        Object.keys(headers).length > 0 ? Object.keys(headers) : undefined,\n      hasAuthProvider: !!options?.authProvider,\n    });\n\n    await client.connect(transport);\n  }\n\n  debugClient('Connected successfully');\n  const serverInfo = client.getServerVersion();\n  if (serverInfo) {\n    debugClient('Server info: %O', serverInfo);\n  }\n\n  return client;\n}\n\n/**\n * Safely closes an MCP client connection\n *\n * @param client - The client to close\n */\nexport async function closeMCPClient(client: Client): Promise<void> {\n  try {\n    await client.close();\n  } catch (error) {\n    console.error('[MCP] Error closing client:', error);\n    throw error;\n  }\n}\n","import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\n\n/**\n * A single content block from an MCP response\n */\nexport interface ContentBlock {\n  type: string;\n  text?: string;\n  data?: unknown;\n  mimeType?: string;\n}\n\n/**\n * Normalized representation of an MCP tool response\n *\n * This provides a consistent interface regardless of the response format\n * returned by the MCP server.\n */\nexport interface NormalizedToolResponse {\n  /**\n   * Extracted text content (concatenated from all text blocks)\n   */\n  text: string;\n\n  /**\n   * Original raw response from the MCP SDK\n   */\n  raw: CallToolResult;\n\n  /**\n   * Whether the tool call resulted in an error\n   */\n  isError: boolean;\n\n  /**\n   * Parsed content blocks from the response\n   */\n  contentBlocks: ContentBlock[];\n\n  /**\n   * Structured content if present (parsed JSON or raw data)\n   */\n  structuredContent: unknown;\n}\n\n/**\n * Normalizes an MCP CallToolResult into a consistent format\n *\n * @param result - Raw CallToolResult from the MCP SDK\n * @returns Normalized response with extracted text, content blocks, etc.\n *\n * @example\n * ```typescript\n * const result = await client.callTool({ name: 'read_file', arguments: { path: 'readme.txt' } });\n * const normalized = normalizeToolResponse(result);\n *\n * console.log(normalized.text);           // \"Hello World\"\n * console.log(normalized.isError);        // false\n * console.log(normalized.contentBlocks);  // [{ type: 'text', text: 'Hello World' }]\n * ```\n */\nexport function normalizeToolResponse(\n  result: CallToolResult\n): NormalizedToolResponse {\n  const isError = result.isError ?? false;\n  const contentBlocks: ContentBlock[] = [];\n  const textParts: string[] = [];\n\n  // Parse content array if present\n  if (Array.isArray(result.content)) {\n    for (const block of result.content) {\n      if (block == null || typeof block !== 'object') {\n        continue;\n      }\n\n      const b = block as Record<string, unknown>;\n      const contentBlock: ContentBlock = {\n        type: typeof b.type === 'string' ? b.type : 'unknown',\n      };\n\n      // Extract text if present\n      if (typeof b.text === 'string') {\n        contentBlock.text = b.text;\n        textParts.push(b.text);\n      }\n\n      // Extract data/blob if present\n      if (b.data !== undefined) {\n        contentBlock.data = b.data;\n      }\n\n      // Extract mimeType if present\n      if (typeof b.mimeType === 'string') {\n        contentBlock.mimeType = b.mimeType;\n      }\n\n      contentBlocks.push(contentBlock);\n    }\n  }\n\n  // Handle structuredContent\n  let structuredContent: unknown = null;\n  if (result.structuredContent !== undefined) {\n    structuredContent = result.structuredContent;\n\n    // If no text was extracted from content blocks, try to get text from structuredContent\n    if (textParts.length === 0) {\n      if (typeof result.structuredContent === 'string') {\n        textParts.push(result.structuredContent);\n      } else if (result.structuredContent != null) {\n        // For objects/arrays, stringify for text representation\n        textParts.push(JSON.stringify(result.structuredContent));\n      }\n    }\n  }\n\n  // Build final text by joining all parts\n  const text = textParts.join('\\n');\n\n  return {\n    text,\n    raw: result,\n    isError,\n    contentBlocks,\n    structuredContent,\n  };\n}\n\n/**\n * Extracts just the text content from a normalized or raw response\n *\n * This is a convenience function that works with both:\n * - Raw CallToolResult from the MCP SDK\n * - NormalizedToolResponse from normalizeToolResponse()\n * - Plain strings or other legacy formats\n *\n * @param response - Response in any supported format\n * @returns Extracted text content\n */\nexport function extractText(response: unknown): string {\n  // Handle null/undefined\n  if (response == null) {\n    return '';\n  }\n\n  // Plain string\n  if (typeof response === 'string') {\n    return response;\n  }\n\n  // Already normalized response\n  if (isNormalizedResponse(response)) {\n    return response.text;\n  }\n\n  // Raw CallToolResult - normalize it first\n  if (isCallToolResult(response)) {\n    return normalizeToolResponse(response).text;\n  }\n\n  // Array of content blocks (direct content)\n  if (Array.isArray(response)) {\n    return extractTextFromContentArray(response);\n  }\n\n  // Generic object - try common patterns\n  if (typeof response === 'object') {\n    const r = response as Record<string, unknown>;\n\n    // Check for content array\n    if (Array.isArray(r.content)) {\n      return extractTextFromContentArray(r.content);\n    }\n\n    // Check for structuredContent\n    if (r.structuredContent !== undefined) {\n      if (typeof r.structuredContent === 'string') {\n        return r.structuredContent;\n      }\n      return JSON.stringify(r.structuredContent);\n    }\n\n    // Check for direct text field\n    if (typeof r.text === 'string') {\n      return r.text;\n    }\n\n    // Fallback to JSON\n    return JSON.stringify(r);\n  }\n\n  // Primitives (number, boolean, bigint, symbol)\n  if (\n    typeof response === 'number' ||\n    typeof response === 'boolean' ||\n    typeof response === 'bigint'\n  ) {\n    return String(response);\n  }\n\n  // Symbol or other edge cases\n  return '';\n}\n\n/**\n * Type guard for NormalizedToolResponse\n */\nfunction isNormalizedResponse(value: unknown): value is NormalizedToolResponse {\n  if (value == null || typeof value !== 'object') {\n    return false;\n  }\n  const v = value as Record<string, unknown>;\n  return (\n    typeof v.text === 'string' &&\n    typeof v.isError === 'boolean' &&\n    Array.isArray(v.contentBlocks) &&\n    v.raw !== undefined\n  );\n}\n\n/**\n * Type guard for CallToolResult\n */\nfunction isCallToolResult(value: unknown): value is CallToolResult {\n  if (value == null || typeof value !== 'object') {\n    return false;\n  }\n  const v = value as Record<string, unknown>;\n  // CallToolResult has content array (required) or isError\n  return Array.isArray(v.content) || typeof v.isError === 'boolean';\n}\n\n/**\n * Extracts text from a content block array\n */\nfunction extractTextFromContentArray(content: unknown[]): string {\n  const textParts: string[] = [];\n\n  for (const block of content) {\n    if (block == null || typeof block !== 'object') {\n      continue;\n    }\n    const b = block as Record<string, unknown>;\n    if (b.type === 'text' && typeof b.text === 'string') {\n      textParts.push(b.text);\n    }\n  }\n\n  if (textParts.length > 0) {\n    return textParts.join('\\n');\n  }\n\n  // No text blocks found, stringify the whole array\n  return JSON.stringify(content);\n}\n","/**\n * Validator Utilities\n *\n * Shared utility functions for validation operations.\n * Re-exports core utilities from mcp/response.ts and adds validation-specific helpers.\n */\n\nimport { extractText as extractTextFromResponse } from '../../mcp/response.js';\n\n/**\n * Re-export extractText from mcp/response.ts\n * This extracts text content from any response format.\n */\nexport const extractText = extractTextFromResponse;\n\n/**\n * Gets the size of a response in bytes\n *\n * Serializes the response to JSON (with pretty printing for consistency)\n * and returns the byte length using UTF-8 encoding.\n *\n * @param response - Response in any format\n * @returns Size in bytes\n */\nexport function getResponseSizeBytes(response: unknown): number {\n  if (response === null || response === undefined) {\n    return 0;\n  }\n\n  // For strings, get direct byte length\n  if (typeof response === 'string') {\n    return Buffer.byteLength(response, 'utf8');\n  }\n\n  // For objects/arrays, serialize with formatting\n  const serialized = JSON.stringify(response, null, 2);\n  return Buffer.byteLength(serialized, 'utf8');\n}\n\n/**\n * Converts a response to a string for comparison\n *\n * @param response - Response in any format\n * @returns String representation\n */\nexport function stringifyResponse(response: unknown): string {\n  if (response === null || response === undefined) {\n    return '';\n  }\n\n  if (typeof response === 'string') {\n    return response;\n  }\n\n  return JSON.stringify(response, null, 2);\n}\n\n/**\n * Checks if a response represents an error\n *\n * @param response - Response to check\n * @returns true if the response is an error\n */\nexport function isErrorResponse(response: unknown): boolean {\n  if (response === null || response === undefined) {\n    return false;\n  }\n\n  if (typeof response !== 'object') {\n    return false;\n  }\n\n  const r = response as Record<string, unknown>;\n\n  // Check isError flag directly\n  if (r.isError === true) {\n    return true;\n  }\n\n  // Check for normalized response with isError\n  if ('raw' in r && typeof r.raw === 'object' && r.raw !== null) {\n    const raw = r.raw as Record<string, unknown>;\n    return raw.isError === true;\n  }\n\n  return false;\n}\n\n/**\n * Extracts error message from an error response\n *\n * @param response - Error response\n * @returns Error message or empty string if not an error\n */\nexport function extractErrorMessage(response: unknown): string {\n  if (!isErrorResponse(response)) {\n    return '';\n  }\n\n  // Extract text content which typically contains the error message\n  return extractText(response);\n}\n","/**\n * Response Validator\n *\n * Validates that a response exactly matches an expected value.\n */\n\nimport type { ValidationResult } from './types.js';\nimport { stringifyResponse } from './utils.js';\n\n/**\n * Validates that a response exactly matches the expected value\n *\n * Performs deep equality comparison using JSON serialization.\n *\n * @param actual - The actual response\n * @param expected - The expected response\n * @returns Validation result\n *\n * @example\n * ```typescript\n * const result = validateResponse(response, { status: 'ok', count: 42 });\n * if (!result.pass) {\n *   console.log(result.message);\n * }\n * ```\n */\nexport function validateResponse(\n  actual: unknown,\n  expected: unknown\n): ValidationResult {\n  const actualStr = stringifyResponse(actual);\n  const expectedStr = stringifyResponse(expected);\n\n  if (actualStr === expectedStr) {\n    return {\n      pass: true,\n      message: 'Response matches expected value',\n    };\n  }\n\n  return {\n    pass: false,\n    message: `Response does not match expected value`,\n    details: {\n      actual: truncateForDisplay(actualStr),\n      expected: truncateForDisplay(expectedStr),\n    },\n  };\n}\n\n/**\n * Truncates a string for display in error messages\n */\nfunction truncateForDisplay(str: string, maxLength = 500): string {\n  if (str.length <= maxLength) {\n    return str;\n  }\n  return str.slice(0, maxLength) + '... (truncated)';\n}\n","/**\n * Schema Validator\n *\n * Validates that a response matches a Zod schema.\n */\n\nimport type { ZodType, ZodError } from 'zod';\nimport type { ValidationResult, SchemaValidatorOptions } from './types.js';\nimport { extractText } from './utils.js';\n\n/**\n * Validates that a response matches a Zod schema\n *\n * Attempts to parse the response with the provided Zod schema.\n * If the response is a text representation of JSON, it will be parsed first.\n *\n * @param response - The response to validate\n * @param schema - The Zod schema to validate against\n * @param options - Validation options\n * @returns Validation result\n *\n * @example\n * ```typescript\n * import { z } from 'zod';\n *\n * const WeatherSchema = z.object({\n *   temperature: z.number(),\n *   conditions: z.string(),\n * });\n *\n * const result = validateSchema(response, WeatherSchema);\n * if (!result.pass) {\n *   console.log(result.message);\n * }\n * ```\n */\nexport function validateSchema(\n  response: unknown,\n  schema: ZodType,\n  options: SchemaValidatorOptions = {}\n): ValidationResult {\n  // Get the value to validate\n  const valueToValidate = getValidatableValue(response);\n\n  // If strict mode is enabled and we have an object schema with .strict(),\n  // the schema itself should handle this - the option is for documentation\n  if (options.strict && valueToValidate !== null) {\n    // Strict mode is handled by the schema itself (using z.object().strict())\n    // This option documents the intent but the actual strictness comes from the schema\n  }\n\n  try {\n    // Attempt to parse with the schema\n    schema.parse(valueToValidate);\n\n    return {\n      pass: true,\n      message: 'Response matches schema',\n    };\n  } catch (error) {\n    const zodError = error as ZodError;\n    const issues = formatZodIssues(zodError);\n\n    return {\n      pass: false,\n      message: `Response does not match schema: ${issues}`,\n      details: {\n        issues: zodError.issues,\n      },\n    };\n  }\n}\n\n/**\n * Extracts a validatable value from a response\n *\n * Handles various response formats:\n * - NormalizedToolResponse: extracts structuredContent or parses text\n * - CallToolResult: extracts structuredContent or parses content\n * - Plain objects: used directly\n * - Strings: parsed as JSON\n */\nfunction getValidatableValue(response: unknown): unknown {\n  if (response === null || response === undefined) {\n    return null;\n  }\n\n  // Plain object - use directly (might be a schema-ready value)\n  if (typeof response === 'object' && !Array.isArray(response)) {\n    const r = response as Record<string, unknown>;\n\n    // Check for structuredContent (MCP response with structured data)\n    if ('structuredContent' in r && r.structuredContent !== undefined) {\n      return r.structuredContent;\n    }\n\n    // Check for normalized response format\n    if ('raw' in r && 'text' in r && 'isError' in r && 'contentBlocks' in r) {\n      // It's a NormalizedToolResponse\n      if (r.structuredContent !== undefined) {\n        return r.structuredContent;\n      }\n      // Try to parse text as JSON\n      const text = r.text as string;\n      return tryParseJson(text) ?? response;\n    }\n\n    // Check for raw CallToolResult format\n    if ('content' in r && Array.isArray(r.content)) {\n      // Try to extract and parse text content\n      const text = extractText(response);\n      return tryParseJson(text) ?? response;\n    }\n\n    // Regular object - use as-is\n    return response;\n  }\n\n  // String - try to parse as JSON\n  if (typeof response === 'string') {\n    return tryParseJson(response) ?? response;\n  }\n\n  // Array or primitive - use directly\n  return response;\n}\n\n/**\n * Attempts to parse a string as JSON\n */\nfunction tryParseJson(text: string): unknown {\n  if (!text || typeof text !== 'string') {\n    return null;\n  }\n\n  const trimmed = text.trim();\n  // Quick check for JSON-like strings\n  if (\n    !(trimmed.startsWith('{') || trimmed.startsWith('[')) ||\n    !(trimmed.endsWith('}') || trimmed.endsWith(']'))\n  ) {\n    return null;\n  }\n\n  try {\n    return JSON.parse(trimmed);\n  } catch {\n    return null;\n  }\n}\n\n/**\n * Formats Zod issues into a human-readable string\n */\nfunction formatZodIssues(error: ZodError): string {\n  const issues = error.issues.map((issue) => {\n    const path = issue.path.length > 0 ? issue.path.join('.') : 'root';\n    return `${path}: ${issue.message}`;\n  });\n\n  return issues.join('; ');\n}\n","/**\n * Text Validator\n *\n * Validates that a response contains expected text substrings.\n */\n\nimport type { ValidationResult, TextValidatorOptions } from './types.js';\nimport { extractText } from './utils.js';\n\n/**\n * Validates that a response contains all expected text substrings\n *\n * Extracts text from the response and checks that each expected substring\n * is present. By default, matching is case-sensitive.\n *\n * @param response - The response to validate\n * @param expected - Expected substring(s) to find\n * @param options - Validation options\n * @returns Validation result\n *\n * @example\n * ```typescript\n * const result = validateText(response, ['temperature', 'conditions']);\n * if (!result.pass) {\n *   console.log(result.message);\n * }\n *\n * // Case-insensitive matching\n * const result2 = validateText(response, 'HELLO', { caseSensitive: false });\n * ```\n */\nexport function validateText(\n  response: unknown,\n  expected: string | string[],\n  options: TextValidatorOptions = {}\n): ValidationResult {\n  const { caseSensitive = true } = options;\n\n  // Normalize expected to array\n  const expectedStrings = Array.isArray(expected) ? expected : [expected];\n\n  // Extract text from response\n  const text = extractText(response);\n\n  // Apply case sensitivity\n  const compareText = caseSensitive ? text : text.toLowerCase();\n\n  // Check each expected substring\n  const missing: string[] = [];\n  for (const substring of expectedStrings) {\n    const compareSubstring = caseSensitive\n      ? substring\n      : substring.toLowerCase();\n\n    if (!compareText.includes(compareSubstring)) {\n      missing.push(substring);\n    }\n  }\n\n  if (missing.length === 0) {\n    return {\n      pass: true,\n      message:\n        expectedStrings.length === 1\n          ? `Response contains expected text`\n          : `Response contains all ${expectedStrings.length} expected substrings`,\n    };\n  }\n\n  return {\n    pass: false,\n    message:\n      missing.length === 1\n        ? `Response does not contain expected text: \"${missing[0]}\"`\n        : `Response is missing ${missing.length} expected substrings: ${missing.map((s) => `\"${s}\"`).join(', ')}`,\n    details: {\n      missing,\n      textLength: text.length,\n      textPreview: truncateForDisplay(text),\n    },\n  };\n}\n\n/**\n * Truncates a string for display in error messages\n */\nfunction truncateForDisplay(str: string, maxLength = 200): string {\n  if (str.length <= maxLength) {\n    return str;\n  }\n  return str.slice(0, maxLength) + '... (truncated)';\n}\n","/**\n * Pattern Validator\n *\n * Validates that a response matches regex patterns.\n */\n\nimport type { ValidationResult, PatternValidatorOptions } from './types.js';\nimport { extractText } from './utils.js';\n\n/**\n * Validates that a response matches all expected regex patterns\n *\n * Extracts text from the response and checks that each pattern matches.\n * Patterns can be strings (which are compiled to RegExp) or RegExp objects.\n *\n * @param response - The response to validate\n * @param patterns - Expected pattern(s) to match\n * @param options - Validation options\n * @returns Validation result\n *\n * @example\n * ```typescript\n * // String pattern\n * const result = validatePattern(response, 'temperature: \\\\d+');\n *\n * // RegExp pattern\n * const result2 = validatePattern(response, /temperature: \\d+/);\n *\n * // Multiple patterns\n * const result3 = validatePattern(response, [\n *   /temperature: \\d+/,\n *   /humidity: \\d+%/,\n * ]);\n *\n * // Case-insensitive matching\n * const result4 = validatePattern(response, 'HELLO', { caseSensitive: false });\n * ```\n */\nexport function validatePattern(\n  response: unknown,\n  patterns: string | RegExp | (string | RegExp)[],\n  options: PatternValidatorOptions = {}\n): ValidationResult {\n  const { caseSensitive = true } = options;\n  const caseInsensitive = !caseSensitive;\n\n  // Normalize patterns to array\n  const patternList = Array.isArray(patterns) ? patterns : [patterns];\n\n  // Extract text from response\n  const text = extractText(response);\n\n  // Check each pattern\n  const unmatched: string[] = [];\n  for (const pattern of patternList) {\n    const regex = toRegExp(pattern, caseInsensitive);\n    if (!regex.test(text)) {\n      unmatched.push(patternToString(pattern));\n    }\n  }\n\n  if (unmatched.length === 0) {\n    return {\n      pass: true,\n      message:\n        patternList.length === 1\n          ? `Response matches pattern`\n          : `Response matches all ${patternList.length} patterns`,\n    };\n  }\n\n  return {\n    pass: false,\n    message:\n      unmatched.length === 1\n        ? `Response does not match pattern: ${unmatched[0]}`\n        : `Response does not match ${unmatched.length} patterns: ${unmatched.join(', ')}`,\n    details: {\n      unmatched,\n      textLength: text.length,\n      textPreview: truncateForDisplay(text),\n    },\n  };\n}\n\n/**\n * Converts a pattern to a RegExp\n */\nfunction toRegExp(pattern: string | RegExp, caseInsensitive: boolean): RegExp {\n  if (pattern instanceof RegExp) {\n    // If caseInsensitive option is set but regex doesn't have it, add it\n    if (caseInsensitive && !pattern.flags.includes('i')) {\n      return new RegExp(pattern.source, pattern.flags + 'i');\n    }\n    return pattern;\n  }\n\n  // Compile string to RegExp\n  const flags = caseInsensitive ? 'i' : '';\n  return new RegExp(pattern, flags);\n}\n\n/**\n * Converts a pattern to a display string\n */\nfunction patternToString(pattern: string | RegExp): string {\n  if (pattern instanceof RegExp) {\n    return pattern.toString();\n  }\n  return `/${pattern}/`;\n}\n\n/**\n * Truncates a string for display in error messages\n */\nfunction truncateForDisplay(str: string, maxLength = 200): string {\n  if (str.length <= maxLength) {\n    return str;\n  }\n  return str.slice(0, maxLength) + '... (truncated)';\n}\n","/**\n * Error Validator\n *\n * Validates error response behavior.\n */\n\nimport type { ValidationResult } from './types.js';\nimport { isErrorResponse, extractErrorMessage, extractText } from './utils.js';\n\n/**\n * Validates that a response is (or is not) an error\n *\n * Can check for:\n * - Any error (expected = true)\n * - No error (expected = false)\n * - Error with specific message(s) (expected = string or string[])\n *\n * @param response - The response to validate\n * @param expected - What to expect (true for any error, false for no error, string for specific message)\n * @returns Validation result\n *\n * @example\n * ```typescript\n * // Expect any error\n * const result = validateError(response, true);\n *\n * // Expect no error\n * const result2 = validateError(response, false);\n *\n * // Expect error with specific message\n * const result3 = validateError(response, 'File not found');\n *\n * // Expect error containing one of several messages\n * const result4 = validateError(response, ['not found', 'does not exist']);\n * ```\n */\nexport function validateError(\n  response: unknown,\n  expected: boolean | string | string[] = true\n): ValidationResult {\n  const actualIsError = isErrorResponse(response);\n  const errorMessage = actualIsError ? extractErrorMessage(response) : '';\n\n  // Handle boolean expectation\n  if (typeof expected === 'boolean') {\n    if (expected) {\n      // Expect an error\n      if (actualIsError) {\n        return {\n          pass: true,\n          message: 'Response is an error as expected',\n        };\n      }\n      return {\n        pass: false,\n        message: 'Expected an error response but got success',\n        details: {\n          textPreview: truncateForDisplay(extractText(response)),\n        },\n      };\n    } else {\n      // Expect no error\n      if (!actualIsError) {\n        return {\n          pass: true,\n          message: 'Response is not an error as expected',\n        };\n      }\n      return {\n        pass: false,\n        message: `Expected a success response but got error: \"${truncateForDisplay(errorMessage)}\"`,\n        details: {\n          errorMessage,\n        },\n      };\n    }\n  }\n\n  // Handle string or string[] expectation\n  const expectedMessages = Array.isArray(expected) ? expected : [expected];\n\n  // Must be an error first\n  if (!actualIsError) {\n    return {\n      pass: false,\n      message: `Expected an error containing \"${expectedMessages[0]}\" but got success`,\n      details: {\n        textPreview: truncateForDisplay(extractText(response)),\n      },\n    };\n  }\n\n  // Check if error message contains any of the expected strings\n  const matched = expectedMessages.some((msg) =>\n    errorMessage.toLowerCase().includes(msg.toLowerCase())\n  );\n\n  if (matched) {\n    return {\n      pass: true,\n      message: 'Error message contains expected text',\n    };\n  }\n\n  return {\n    pass: false,\n    message:\n      expectedMessages.length === 1\n        ? `Error message does not contain \"${expectedMessages[0]}\"`\n        : `Error message does not contain any of: ${expectedMessages.map((m) => `\"${m}\"`).join(', ')}`,\n    details: {\n      actualErrorMessage: errorMessage,\n      expectedToContain: expectedMessages,\n    },\n  };\n}\n\n/**\n * Truncates a string for display in error messages\n */\nfunction truncateForDisplay(str: string, maxLength = 200): string {\n  if (str.length <= maxLength) {\n    return str;\n  }\n  return str.slice(0, maxLength) + '... (truncated)';\n}\n","/**\n * Size Validator\n *\n * Validates that a response meets size constraints.\n */\n\nimport type { ValidationResult, SizeValidatorOptions } from './types.js';\nimport { getResponseSizeBytes } from './utils.js';\n\n/**\n * Validates that a response meets size constraints\n *\n * Checks that the response size in bytes is within the specified bounds.\n * At least one of minBytes or maxBytes must be provided.\n *\n * @param response - The response to validate\n * @param options - Size constraints\n * @returns Validation result\n *\n * @example\n * ```typescript\n * // Maximum size check\n * const result = validateSize(response, { maxBytes: 10000 });\n *\n * // Minimum size check\n * const result2 = validateSize(response, { minBytes: 100 });\n *\n * // Both bounds\n * const result3 = validateSize(response, { minBytes: 100, maxBytes: 10000 });\n * ```\n */\nexport function validateSize(\n  response: unknown,\n  options: SizeValidatorOptions\n): ValidationResult {\n  const { maxBytes, minBytes } = options;\n\n  // Require at least one bound\n  if (maxBytes === undefined && minBytes === undefined) {\n    return {\n      pass: false,\n      message: 'Size validation requires at least one of maxBytes or minBytes',\n    };\n  }\n\n  const actualSize = getResponseSizeBytes(response);\n  const issues: string[] = [];\n\n  // Check minimum\n  if (minBytes !== undefined && actualSize < minBytes) {\n    issues.push(\n      `Response size (${formatBytes(actualSize)}) is below minimum (${formatBytes(minBytes)})`\n    );\n  }\n\n  // Check maximum\n  if (maxBytes !== undefined && actualSize > maxBytes) {\n    issues.push(\n      `Response size (${formatBytes(actualSize)}) exceeds maximum (${formatBytes(maxBytes)})`\n    );\n  }\n\n  if (issues.length === 0) {\n    return {\n      pass: true,\n      message: `Response size (${formatBytes(actualSize)}) is within bounds`,\n      details: {\n        actualBytes: actualSize,\n      },\n    };\n  }\n\n  return {\n    pass: false,\n    message: issues.join('; '),\n    details: {\n      actualBytes: actualSize,\n      minBytes,\n      maxBytes,\n    },\n  };\n}\n\n/**\n * Formats bytes as a human-readable string\n */\nfunction formatBytes(bytes: number): string {\n  if (bytes < 1024) {\n    return `${bytes} bytes`;\n  }\n  if (bytes < 1024 * 1024) {\n    return `${(bytes / 1024).toFixed(1)} KB`;\n  }\n  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n","import type { TestInfo } from '@playwright/test';\nimport type { Client } from '@modelcontextprotocol/sdk/client/index.js';\nimport type {\n  Tool,\n  CallToolResult,\n  ListToolsResult,\n} from '@modelcontextprotocol/sdk/types.js';\nimport type { AuthType } from '../../types/index.js';\n\n// Re-export AuthType for backwards compatibility\nexport type { AuthType } from '../../types/index.js';\n\n// Dynamic import of test for conditional step tracking\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet testStep:\n  | ((name: string, fn: () => Promise<unknown>) => Promise<unknown>)\n  | null = null;\n\n// Try to load test.step() dynamically\ntry {\n  /* eslint-disable @typescript-eslint/no-require-imports, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call */\n  const playwright = require('@playwright/test');\n  if (playwright && playwright.test && playwright.test.step) {\n    testStep = playwright.test.step.bind(playwright.test) as typeof testStep;\n  }\n  /* eslint-enable @typescript-eslint/no-require-imports, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call */\n} catch {\n  // Not in a test context, that's fine\n}\n\n/**\n * Options for creating an MCP fixture\n */\nexport interface MCPFixtureOptions {\n  /**\n   * Authentication type used for this test\n   * - 'oauth': Interactive OAuth 2.1 with PKCE (browser-based authentication)\n   * - 'api-token': Static API token (e.g., from a dashboard or environment variable)\n   * - 'none': No authentication\n   */\n  authType?: AuthType;\n\n  /**\n   * Playwright project name for this test\n   * Used for filtering and grouping in the reporter\n   */\n  project?: string;\n}\n\n/**\n * High-level API for interacting with MCP servers in tests\n *\n * This interface wraps the raw MCP Client with test-friendly methods\n */\nexport interface MCPFixtureApi {\n  /**\n   * The underlying MCP client (for advanced usage)\n   */\n  client: Client;\n\n  /**\n   * Authentication type used for this test session\n   */\n  authType: AuthType;\n\n  /**\n   * Playwright project name for this test session\n   */\n  project?: string;\n\n  /**\n   * Lists all available tools from the MCP server\n   *\n   * @returns Array of tool definitions\n   */\n  listTools(): Promise<Array<Tool>>;\n\n  /**\n   * Calls a tool on the MCP server\n   *\n   * @param name - Tool name\n   * @param args - Tool arguments\n   * @returns Tool call result\n   */\n  callTool<TArgs extends Record<string, unknown> = Record<string, unknown>>(\n    name: string,\n    args: TArgs\n  ): Promise<CallToolResult>;\n\n  /**\n   * Gets information about the connected server\n   */\n  getServerInfo(): {\n    name?: string;\n    version?: string;\n  } | null;\n}\n\n/**\n * Creates an MCP fixture wrapper around a Client\n *\n * When testInfo is provided, automatically tracks all MCP operations with test.step()\n * and creates attachments for the MCP Test Reporter.\n *\n * @param client - The MCP client to wrap\n * @param testInfo - Optional Playwright TestInfo for auto-tracking\n * @returns MCPFixtureApi instance\n *\n * @example\n * ```typescript\n * // With tracking (recommended)\n * const test = base.extend<{ mcp: MCPFixtureApi }>({\n *   mcp: async ({}, use, testInfo) => {\n *     const client = await createMCPClientForConfig(config);\n *     const api = createMCPFixture(client, testInfo);\n *     await use(api);\n *     await closeMCPClient(client);\n *   }\n * });\n *\n * // Without tracking\n * const api = createMCPFixture(client);\n * ```\n */\nexport function createMCPFixture(\n  client: Client,\n  testInfo?: TestInfo,\n  options?: MCPFixtureOptions\n): MCPFixtureApi {\n  const authType = options?.authType ?? 'none';\n  const project = options?.project;\n  // If no testInfo, return basic API without tracking\n  if (!testInfo) {\n    return {\n      client,\n      authType,\n      project,\n\n      async listTools(): Promise<Array<Tool>> {\n        const result = (await client.listTools()) as ListToolsResult;\n        return result.tools;\n      },\n\n      async callTool<TArgs extends Record<string, unknown>>(\n        name: string,\n        args: TArgs\n      ): Promise<CallToolResult> {\n        const result = (await client.callTool({\n          name,\n          arguments: args,\n        })) as CallToolResult;\n        return result;\n      },\n\n      getServerInfo() {\n        const serverVersion = client.getServerVersion();\n        if (!serverVersion) {\n          return null;\n        }\n        return {\n          name: serverVersion.name,\n          version: serverVersion.version,\n        };\n      },\n    };\n  }\n\n  // With testInfo, return tracked API\n  return {\n    client,\n    authType,\n    project,\n\n    async listTools(): Promise<Array<Tool>> {\n      const execute = async () => {\n        const result = (await client.listTools()) as ListToolsResult;\n        const tools = result.tools;\n\n        // Auto-attach for reporter\n        await testInfo.attach('mcp-list-tools', {\n          contentType: 'application/json',\n          body: JSON.stringify(\n            {\n              operation: 'listTools',\n              toolCount: tools.length,\n              tools: tools.map((t) => ({\n                name: t.name,\n                description: t.description,\n              })),\n            },\n            null,\n            2\n          ),\n        });\n\n        return tools;\n      };\n\n      // Wrap in test.step if available\n      return (\n        testStep ? testStep('MCP: listTools()', execute) : execute()\n      ) as Promise<Array<Tool>>;\n    },\n\n    async callTool<TArgs extends Record<string, unknown>>(\n      name: string,\n      args: TArgs\n    ): Promise<CallToolResult> {\n      const execute = async () => {\n        const startTime = Date.now();\n        const result = (await client.callTool({\n          name,\n          arguments: args,\n        })) as CallToolResult;\n        const durationMs = Date.now() - startTime;\n\n        // Auto-attach for reporter\n        await testInfo.attach(`mcp-call-${name}`, {\n          contentType: 'application/json',\n          body: JSON.stringify(\n            {\n              operation: 'callTool',\n              toolName: name,\n              args,\n              result,\n              durationMs,\n              isError: result.isError || false,\n              authType,\n              project,\n            },\n            null,\n            2\n          ),\n        });\n\n        return result;\n      };\n\n      // Wrap in test.step if available\n      return (\n        testStep ? testStep(`MCP: callTool(\"${name}\")`, execute) : execute()\n      ) as Promise<CallToolResult>;\n    },\n\n    getServerInfo() {\n      const serverVersion = client.getServerVersion();\n      const result = serverVersion\n        ? {\n            name: serverVersion.name,\n            version: serverVersion.version,\n          }\n        : null;\n\n      // Fire-and-forget attachment (don't block synchronous call)\n      testInfo\n        .attach('mcp-server-info', {\n          contentType: 'application/json',\n          body: JSON.stringify(\n            {\n              operation: 'getServerInfo',\n              serverInfo: result,\n            },\n            null,\n            2\n          ),\n        })\n        .catch(() => {\n          // Ignore attachment errors for sync methods\n        });\n\n      return result;\n    },\n  };\n}\n","/**\n * toMatchToolResponse Matcher\n *\n * Validates that a response exactly matches an expected value.\n */\n\nimport { validateResponse } from '../validators/response.js';\n\n/**\n * Creates the toMatchToolResponse matcher function\n */\nexport function toMatchToolResponse(\n  this: { isNot: boolean },\n  received: unknown,\n  expected: unknown\n) {\n  const result = validateResponse(received, expected);\n\n  return {\n    pass: result.pass,\n    message: () => {\n      if (this.isNot) {\n        return result.pass\n          ? 'Expected response NOT to match, but it did'\n          : result.message;\n      }\n      return result.message;\n    },\n  };\n}\n","/**\n * toMatchToolSchema Matcher\n *\n * Validates that a response matches a Zod schema.\n */\n\nimport type { ZodType } from 'zod';\nimport { validateSchema } from '../validators/schema.js';\nimport type { SchemaValidatorOptions } from '../validators/types.js';\n\n/**\n * Creates the toMatchToolSchema matcher function\n */\nexport function toMatchToolSchema(\n  this: { isNot: boolean },\n  received: unknown,\n  schema: ZodType,\n  options: SchemaValidatorOptions = {}\n) {\n  const result = validateSchema(received, schema, options);\n\n  return {\n    pass: result.pass,\n    message: () => {\n      if (this.isNot) {\n        return result.pass\n          ? 'Expected response NOT to match schema, but it did'\n          : result.message;\n      }\n      return result.message;\n    },\n  };\n}\n","/**\n * toContainToolText Matcher\n *\n * Validates that a response contains expected text substrings.\n */\n\nimport { validateText } from '../validators/text.js';\nimport type { TextValidatorOptions } from '../validators/types.js';\n\n/**\n * Creates the toContainToolText matcher function\n */\nexport function toContainToolText(\n  this: { isNot: boolean },\n  received: unknown,\n  expected: string | string[],\n  options: TextValidatorOptions = {}\n) {\n  const result = validateText(received, expected, options);\n\n  return {\n    pass: result.pass,\n    message: () => {\n      if (this.isNot) {\n        const expectedStr = Array.isArray(expected)\n          ? expected.map((s) => `\"${s}\"`).join(', ')\n          : `\"${expected}\"`;\n        return result.pass\n          ? `Expected response NOT to contain ${expectedStr}, but it did`\n          : result.message;\n      }\n      return result.message;\n    },\n  };\n}\n","/**\n * toMatchToolPattern Matcher\n *\n * Validates that a response matches regex patterns.\n */\n\nimport { validatePattern } from '../validators/pattern.js';\nimport type { PatternValidatorOptions } from '../validators/types.js';\n\n/**\n * Creates the toMatchToolPattern matcher function\n */\nexport function toMatchToolPattern(\n  this: { isNot: boolean },\n  received: unknown,\n  patterns: string | RegExp | (string | RegExp)[],\n  options: PatternValidatorOptions = {}\n) {\n  const result = validatePattern(received, patterns, options);\n\n  return {\n    pass: result.pass,\n    message: () => {\n      if (this.isNot) {\n        return result.pass\n          ? 'Expected response NOT to match pattern(s), but it did'\n          : result.message;\n      }\n      return result.message;\n    },\n  };\n}\n","/**\n * toMatchToolSnapshot Matcher\n *\n * Validates that a response matches a saved snapshot.\n * Uses Playwright's native snapshot testing functionality.\n */\n\nimport { expect as baseExpect } from '@playwright/test';\nimport type { SnapshotSanitizer } from '../validators/types.js';\nimport { extractText } from '../validators/utils.js';\n\n/**\n * Built-in regex patterns for common variable data\n */\nconst BUILT_IN_PATTERNS: Record<\n  string,\n  { pattern: RegExp; replacement: string }\n> = {\n  timestamp: {\n    pattern: /\\b\\d{10,13}\\b/g,\n    replacement: '[TIMESTAMP]',\n  },\n  uuid: {\n    pattern:\n      /\\b[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\\b/gi,\n    replacement: '[UUID]',\n  },\n  'iso-date': {\n    pattern:\n      /\\b\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,3})?(Z|[+-]\\d{2}:?\\d{2})?)?\\b/g,\n    replacement: '[ISO_DATE]',\n  },\n  objectId: {\n    pattern: /\\b[0-9a-f]{24}\\b/gi,\n    replacement: '[OBJECT_ID]',\n  },\n  jwt: {\n    pattern: /\\beyJ[A-Za-z0-9_-]*\\.eyJ[A-Za-z0-9_-]*\\.[A-Za-z0-9_-]+\\b/g,\n    replacement: '[JWT]',\n  },\n};\n\n/**\n * Type guard for regex sanitizer\n */\nfunction isRegexSanitizer(\n  sanitizer: SnapshotSanitizer\n): sanitizer is { pattern: string | RegExp; replacement?: string } {\n  return (\n    typeof sanitizer === 'object' &&\n    sanitizer !== null &&\n    'pattern' in sanitizer\n  );\n}\n\n/**\n * Type guard for field removal sanitizer\n */\nfunction isFieldRemovalSanitizer(\n  sanitizer: SnapshotSanitizer\n): sanitizer is { remove: string[] } {\n  return (\n    typeof sanitizer === 'object' && sanitizer !== null && 'remove' in sanitizer\n  );\n}\n\n/**\n * Apply sanitizers to a string value\n *\n * Handles three types of sanitizers:\n * 1. Built-in names: 'timestamp', 'uuid', 'iso-date', 'objectId', 'jwt'\n * 2. Regex sanitizers: { pattern: string | RegExp, replacement?: string }\n * 3. Field removal sanitizers: { remove: string[] } - only works on JSON strings\n */\nfunction applySanitizers(\n  value: string,\n  sanitizers: SnapshotSanitizer[]\n): string {\n  let result = value;\n\n  for (const sanitizer of sanitizers) {\n    // Handle built-in sanitizer names\n    if (typeof sanitizer === 'string') {\n      const builtIn = BUILT_IN_PATTERNS[sanitizer];\n      if (builtIn) {\n        result = result.replace(builtIn.pattern, builtIn.replacement);\n      }\n      continue;\n    }\n\n    // Handle regex sanitizers\n    if (isRegexSanitizer(sanitizer)) {\n      const pattern =\n        sanitizer.pattern instanceof RegExp\n          ? sanitizer.pattern\n          : new RegExp(sanitizer.pattern, 'g');\n      const replacement = sanitizer.replacement ?? '[SANITIZED]';\n      result = result.replace(pattern, replacement);\n      continue;\n    }\n\n    // Handle field removal sanitizers\n    if (isFieldRemovalSanitizer(sanitizer)) {\n      try {\n        const parsed: unknown = JSON.parse(result);\n        removeFields(parsed, sanitizer.remove);\n        result = JSON.stringify(parsed, null, 2);\n      } catch {\n        // Not valid JSON, skip field removal\n      }\n    }\n  }\n\n  return result;\n}\n\n/**\n * Remove fields from an object by dot-notation paths\n */\nfunction removeFields(obj: unknown, paths: string[]): void {\n  if (typeof obj !== 'object' || obj === null) {\n    return;\n  }\n\n  for (const path of paths) {\n    const parts = path.split('.');\n    if (parts.length === 0) {\n      continue;\n    }\n\n    let current: unknown = obj;\n\n    // Navigate to parent of target field\n    for (let i = 0; i < parts.length - 1; i++) {\n      if (typeof current !== 'object' || current === null) {\n        break;\n      }\n      const key = parts[i];\n      if (key !== undefined) {\n        current = (current as Record<string, unknown>)[key];\n      }\n    }\n\n    // Delete the target field\n    if (typeof current === 'object' && current !== null) {\n      const lastKey = parts[parts.length - 1];\n      if (lastKey !== undefined) {\n        delete (current as Record<string, unknown>)[lastKey];\n      }\n    }\n  }\n}\n\n/**\n * Creates the toMatchToolSnapshot matcher function\n *\n * Note: This is an async matcher that uses Playwright's snapshot testing.\n */\nexport async function toMatchToolSnapshot(\n  this: { isNot: boolean },\n  received: unknown,\n  name: string,\n  sanitizers: SnapshotSanitizer[] = []\n): Promise<{ pass: boolean; message: () => string }> {\n  // Extract text content from response\n  let content = extractText(received);\n\n  // Apply sanitizers\n  if (sanitizers.length > 0) {\n    content = applySanitizers(content, sanitizers);\n  }\n\n  // .not is not really meaningful for snapshots, but handle it gracefully\n  if (this.isNot) {\n    // For .not, we want to verify it does NOT match - this is unusual for snapshots\n    // but we can try and check if it throws\n    try {\n      // eslint-disable-next-line @typescript-eslint/await-thenable\n      await baseExpect(content).toMatchSnapshot(name);\n      // If it didn't throw, the snapshot matched - so .not fails\n      return {\n        pass: false,\n        message: () =>\n          `Expected response NOT to match snapshot \"${name}\", but it did`,\n      };\n    } catch {\n      // Snapshot didn't match - .not passes\n      return {\n        pass: true,\n        message: () => `Response does not match snapshot \"${name}\" as expected`,\n      };\n    }\n  }\n\n  try {\n    // Use Playwright's native snapshot testing\n    // eslint-disable-next-line @typescript-eslint/await-thenable\n    await baseExpect(content).toMatchSnapshot(name);\n    return {\n      pass: true,\n      message: () => `Response matches snapshot \"${name}\"`,\n    };\n  } catch (error) {\n    return {\n      pass: false,\n      message: () =>\n        error instanceof Error\n          ? error.message\n          : `Response does not match snapshot \"${name}\"`,\n    };\n  }\n}\n\nexport { BUILT_IN_PATTERNS, applySanitizers };\n","/**\n * toBeToolError Matcher\n *\n * Validates that a response is (or is not) an error.\n */\n\nimport { validateError } from '../validators/error.js';\n\n/**\n * Creates the toBeToolError matcher function\n */\nexport function toBeToolError(\n  this: { isNot: boolean },\n  received: unknown,\n  expected: boolean | string | string[] = true\n) {\n  // Handle .not case specially\n  const effectiveExpected = this.isNot\n    ? typeof expected === 'boolean'\n      ? !expected\n      : false // .not with string message means \"should not be error\"\n    : expected;\n\n  const result = validateError(received, effectiveExpected);\n\n  return {\n    pass: this.isNot ? !result.pass : result.pass,\n    message: () => {\n      if (this.isNot) {\n        // When using .not, we want the opposite behavior\n        if (typeof expected === 'boolean') {\n          return result.pass\n            ? 'Expected response NOT to be an error, but it was'\n            : 'Response is not an error as expected';\n        }\n        const expectedStr = Array.isArray(expected)\n          ? expected.join(', ')\n          : expected;\n        return result.pass\n          ? `Expected response NOT to be an error with \"${expectedStr}\", but it was`\n          : result.message;\n      }\n      return result.message;\n    },\n  };\n}\n","import { query } from '@anthropic-ai/claude-agent-sdk';\nimport type {\n  JudgeConfig,\n  Judge,\n  JudgeResult,\n  UsageMetrics,\n} from './judgeTypes.js';\n\n/**\n * Creates a Claude Agent SDK-based LLM judge client\n *\n * Uses the Claude Agent SDK query() function for evaluation.\n * This is a response-only judge that does not use any tools.\n *\n * @param config - Judge configuration\n * @returns Claude agent judge client\n */\nexport function createClaudeAgentJudge(config: JudgeConfig): Judge {\n  const model = config.model ?? 'claude-sonnet-4-20250514';\n  const maxBudgetUsd = config.maxBudgetUsd ?? 0.1;\n  const maxToolOutputSize = config.maxToolOutputSize;\n\n  return {\n    async evaluate(\n      candidate: unknown,\n      reference: unknown,\n      rubric: string\n    ): Promise<JudgeResult> {\n      // Calculate candidate size for threshold check\n      const candidateStr =\n        typeof candidate === 'string'\n          ? candidate\n          : JSON.stringify(candidate, null, 2);\n      const candidateSizeBytes = Buffer.byteLength(candidateStr, 'utf8');\n\n      // Check maxToolOutputSize threshold before calling API (fail fast, save money)\n      if (\n        maxToolOutputSize !== undefined &&\n        candidateSizeBytes > maxToolOutputSize\n      ) {\n        return {\n          pass: false,\n          score: 0,\n          reasoning: `Tool output size (${candidateSizeBytes} bytes) exceeds maximum allowed size (${maxToolOutputSize} bytes)`,\n          candidateSizeBytes,\n          exceedsMaxToolOutputSize: true,\n        };\n      }\n\n      // Build evaluation prompt\n      const prompt = buildJudgePrompt(candidate, reference, rubric);\n\n      try {\n        // Use query() with no tools for response-only mode\n        // Iterate through the generator to get the final result message\n        let resultMessage:\n          | {\n              type: 'result';\n              result?: string;\n              usage?: {\n                input_tokens: number;\n                output_tokens: number;\n                cache_read_input_tokens?: number;\n                cache_creation_input_tokens?: number;\n              };\n              total_cost_usd?: number;\n              duration_ms?: number;\n              duration_api_ms?: number;\n              subtype?: string;\n              errors?: string[];\n            }\n          | undefined;\n\n        for await (const message of query({\n          prompt,\n          options: {\n            model,\n            maxBudgetUsd,\n            // Use empty tools array for response-only mode\n            tools: [],\n            // Bypass permissions since we're not using any tools\n            permissionMode: 'bypassPermissions',\n            allowDangerouslySkipPermissions: true,\n            // Use a custom system prompt for JSON output\n            systemPrompt: buildSystemPrompt(),\n            // Limit to 1 turn since this is a simple evaluation\n            maxTurns: 1,\n          },\n        })) {\n          // The final message will be the SDKResultMessage\n          if (message.type === 'result') {\n            resultMessage = message as unknown as typeof resultMessage;\n          }\n        }\n\n        if (!resultMessage) {\n          throw new Error('No result message received from Claude Agent SDK');\n        }\n\n        // Check for errors\n        if (\n          resultMessage.subtype !== 'success' &&\n          resultMessage.errors?.length\n        ) {\n          throw new Error(\n            `Claude Agent SDK error: ${resultMessage.errors.join(', ')}`\n          );\n        }\n\n        // Extract text response from the result\n        const responseText = resultMessage.result ?? '';\n\n        // Parse the JSON response\n        const parsed = parseJudgeResponse(responseText);\n\n        // Build usage metrics from SDK response\n        const usage: UsageMetrics = {\n          inputTokens: resultMessage.usage?.input_tokens ?? 0,\n          outputTokens: resultMessage.usage?.output_tokens ?? 0,\n          totalCostUsd: resultMessage.total_cost_usd ?? 0,\n          durationMs: resultMessage.duration_ms ?? 0,\n          durationApiMs: resultMessage.duration_api_ms,\n          cacheReadInputTokens: resultMessage.usage?.cache_read_input_tokens,\n          cacheCreationInputTokens:\n            resultMessage.usage?.cache_creation_input_tokens,\n        };\n\n        return {\n          pass: parsed.pass ?? false,\n          score: parsed.score,\n          reasoning: parsed.reasoning,\n          usage,\n          candidateSizeBytes,\n          exceedsMaxToolOutputSize: false,\n        };\n      } catch (error) {\n        throw new Error(\n          `Claude Agent judge evaluation failed: ${error instanceof Error ? error.message : String(error)}`\n        );\n      }\n    },\n  };\n}\n\n/**\n * Builds the system prompt for the judge\n */\nfunction buildSystemPrompt(): string {\n  return (\n    'You are an expert evaluator. Evaluate the candidate response based on the rubric provided. ' +\n    'Respond ONLY with valid JSON in this exact format: {\"pass\": boolean, \"score\": number (0-1), \"reasoning\": string}. ' +\n    'Do not include any other text, markdown formatting, or code blocks.'\n  );\n}\n\n/**\n * Builds the user prompt for evaluation\n */\nfunction buildJudgePrompt(\n  candidate: unknown,\n  reference: unknown,\n  rubric: string\n): string {\n  const parts: Array<string> = [];\n\n  parts.push('# Evaluation Task\\n');\n  parts.push(rubric);\n  parts.push('\\n\\n# Candidate Response\\n');\n  parts.push(\n    typeof candidate === 'string'\n      ? candidate\n      : JSON.stringify(candidate, null, 2)\n  );\n\n  if (reference !== null && reference !== undefined) {\n    parts.push('\\n\\n# Reference Response\\n');\n    parts.push(\n      typeof reference === 'string'\n        ? reference\n        : JSON.stringify(reference, null, 2)\n    );\n  }\n\n  parts.push(\n    '\\n\\n# Instructions\\n' +\n      'Evaluate the candidate response based on the rubric. ' +\n      (reference !== null && reference !== undefined\n        ? 'Compare it against the reference response if helpful. '\n        : '') +\n      'Respond with JSON containing \"pass\" (boolean), \"score\" (0-1), and \"reasoning\" (string).'\n  );\n\n  return parts.join('');\n}\n\n/**\n * Parses the JSON response from the judge, handling markdown code blocks\n */\nfunction parseJudgeResponse(text: string): {\n  pass?: boolean;\n  score?: number;\n  reasoning?: string;\n} {\n  let jsonText = text.trim();\n\n  // Strip markdown code blocks if present\n  if (jsonText.startsWith('```json')) {\n    jsonText = jsonText.slice(7);\n  }\n  if (jsonText.startsWith('```')) {\n    jsonText = jsonText.slice(3);\n  }\n  if (jsonText.endsWith('```')) {\n    jsonText = jsonText.slice(0, -3);\n  }\n  jsonText = jsonText.trim();\n\n  try {\n    return JSON.parse(jsonText) as {\n      pass?: boolean;\n      score?: number;\n      reasoning?: string;\n    };\n  } catch {\n    // If JSON parsing fails, try to extract from the text\n    // Sometimes the model adds extra text before/after JSON\n    const jsonMatch = jsonText.match(/\\{[\\s\\S]*\"pass\"[\\s\\S]*\\}/);\n    if (jsonMatch) {\n      return JSON.parse(jsonMatch[0]) as {\n        pass?: boolean;\n        score?: number;\n        reasoning?: string;\n      };\n    }\n    throw new Error(`Failed to parse judge response as JSON: ${text}`);\n  }\n}\n","import type { Judge, JudgeConfig, ProviderKind } from './judgeTypes.js';\nimport { createClaudeAgentJudge } from './claudeAgentJudge.js';\n\n/**\n * Creates an LLM judge for evaluating tool responses\n *\n * Uses Claude Agent SDK for evaluation with usage metrics tracking.\n *\n * @param config - Judge configuration\n * @returns Judge instance\n * @throws {Error} If provider is unsupported or configuration is invalid\n *\n * @example\n * // Default Claude judge\n * const judge = createJudge();\n *\n * @example\n * // With configuration\n * const judge = createJudge({\n *   model: 'claude-sonnet-4-20250514',\n *   maxToolOutputSize: 50000, // Fail if response > 50KB\n *   maxBudgetUsd: 0.05,\n * });\n *\n * // Evaluate a response\n * const result = await judge.evaluate(\n *   candidateResponse,\n *   referenceResponse,\n *   'Evaluate for accuracy and completeness'\n * );\n *\n * // Access usage metrics\n * console.log('Cost:', result.usage?.totalCostUsd);\n * console.log('Tokens:', result.usage?.inputTokens, result.usage?.outputTokens);\n */\nexport function createJudge(config: JudgeConfig = {}): Judge {\n  const provider: ProviderKind = config.provider ?? 'claude';\n\n  switch (provider) {\n    case 'claude':\n    case 'anthropic':\n      // Both 'claude' and 'anthropic' use Claude Agent SDK\n      return createClaudeAgentJudge(config);\n\n    case 'openai':\n      throw new Error(\n        'OpenAI provider is no longer supported. ' +\n          'Please use createJudge() without specifying provider, or use provider: \"claude\". ' +\n          'See migration guide at https://github.com/mcp-testing/server-tester/blob/main/docs/migration-v0.11.md'\n      );\n\n    case 'custom-http':\n      throw new Error(\n        'custom-http provider is no longer supported. ' +\n          'Please use createJudge() without specifying provider.'\n      );\n\n    default:\n      throw new Error(`Unsupported LLM provider: ${String(provider)}`);\n  }\n}\n","/**\n * toPassToolJudge Matcher\n *\n * Validates that a response passes LLM-as-judge evaluation.\n */\n\nimport { createJudge } from '../../judge/judgeClient.js';\nimport type { JudgeConfig } from '../../judge/judgeTypes.js';\nimport type { JudgeMatcherOptions } from './types.js';\n\n// Default passing threshold\nconst DEFAULT_PASSING_THRESHOLD = 0.7;\n\n// Default judge configuration\nconst DEFAULT_JUDGE_CONFIG: JudgeConfig = {};\n\n/**\n * Creates the toPassToolJudge matcher function\n *\n * Note: This is an async matcher that calls an LLM for evaluation.\n */\nexport async function toPassToolJudge(\n  this: { isNot: boolean },\n  received: unknown,\n  rubric: string,\n  options: JudgeMatcherOptions = {}\n): Promise<{ pass: boolean; message: () => string }> {\n  const {\n    reference = null,\n    passingThreshold = DEFAULT_PASSING_THRESHOLD,\n    judgeConfig = DEFAULT_JUDGE_CONFIG,\n  } = options;\n\n  // Create judge client\n  const judge = createJudge(judgeConfig);\n\n  try {\n    // Evaluate the response\n    const result = await judge.evaluate(received, reference, rubric);\n\n    // Determine pass/fail based on threshold\n    const score = result.score ?? (result.pass ? 1.0 : 0.0);\n    const passes = score >= passingThreshold;\n\n    if (this.isNot) {\n      // For .not, we expect the evaluation to fail\n      return {\n        pass: !passes,\n        message: () =>\n          passes\n            ? `Expected judge evaluation to fail, but it passed with score ${score.toFixed(2)}`\n            : `Judge evaluation failed as expected with score ${score.toFixed(2)}`,\n      };\n    }\n\n    if (passes) {\n      return {\n        pass: true,\n        message: () =>\n          `Judge evaluation passed with score ${score.toFixed(2)} (threshold: ${passingThreshold})`,\n      };\n    }\n\n    return {\n      pass: false,\n      message: () =>\n        `Judge evaluation failed with score ${score.toFixed(2)} (threshold: ${passingThreshold}). ` +\n        `Reasoning: ${result.reasoning ?? 'No reasoning provided'}`,\n    };\n  } catch (error) {\n    return {\n      pass: false,\n      message: () =>\n        `Judge evaluation failed with error: ${error instanceof Error ? error.message : String(error)}`,\n    };\n  }\n}\n","/**\n * toHaveToolResponseSize Matcher\n *\n * Validates that a response meets size constraints.\n */\n\nimport { validateSize } from '../validators/size.js';\nimport type { SizeValidatorOptions } from '../validators/types.js';\n\n/**\n * Creates the toHaveToolResponseSize matcher function\n */\nexport function toHaveToolResponseSize(\n  this: { isNot: boolean },\n  received: unknown,\n  options: SizeValidatorOptions\n) {\n  const result = validateSize(received, options);\n\n  return {\n    pass: result.pass,\n    message: () => {\n      if (this.isNot) {\n        return result.pass\n          ? 'Expected response size NOT to be within bounds, but it was'\n          : result.message;\n      }\n      return result.message;\n    },\n  };\n}\n","/**\n * toSatisfyToolPredicate Matcher\n *\n * Validates that a response satisfies a custom predicate function.\n * This is an escape hatch for custom validation logic when built-in\n * matchers don't cover the use case.\n */\n\nimport { extractText } from '../validators/utils.js';\nimport type { PredicateResult, ToolPredicate } from './types.js';\n\n/**\n * Normalizes predicate result to PredicateResult object\n */\nfunction normalizeResult(result: boolean | PredicateResult): PredicateResult {\n  if (typeof result === 'boolean') {\n    return {\n      pass: result,\n      message: result ? 'Predicate passed' : 'Predicate returned false',\n    };\n  }\n  return result;\n}\n\n/**\n * Creates the toSatisfyToolPredicate matcher function\n *\n * This matcher allows custom validation logic via a predicate function.\n * The predicate receives both the raw response and extracted text.\n *\n * @example\n * ```typescript\n * // Simple boolean predicate\n * expect(result).toSatisfyToolPredicate((response) => {\n *   return response.data?.length > 0;\n * });\n *\n * // Predicate with custom message\n * expect(result).toSatisfyToolPredicate((response, text) => {\n *   const hasTemperature = text.includes('temperature');\n *   return {\n *     pass: hasTemperature,\n *     message: hasTemperature\n *       ? 'Found temperature in response'\n *       : 'Expected response to contain temperature',\n *   };\n * });\n *\n * // Async predicate\n * expect(result).toSatisfyToolPredicate(async (response) => {\n *   const isValid = await validateWithExternalService(response);\n *   return isValid;\n * });\n * ```\n */\nexport async function toSatisfyToolPredicate(\n  this: { isNot: boolean },\n  received: unknown,\n  predicate: ToolPredicate,\n  description?: string\n): Promise<{ pass: boolean; message: () => string }> {\n  const predicateDescription = description ?? 'custom predicate';\n\n  try {\n    // Extract text for convenience\n    const text = extractText(received);\n\n    // Run the predicate\n    const rawResult = await predicate(received, text);\n    const result = normalizeResult(rawResult);\n\n    // Handle .not\n    if (this.isNot) {\n      return {\n        pass: !result.pass,\n        message: () =>\n          result.pass\n            ? `Expected response NOT to satisfy ${predicateDescription}`\n            : `Response does not satisfy ${predicateDescription} as expected`,\n      };\n    }\n\n    return {\n      pass: result.pass,\n      message: () =>\n        result.pass\n          ? (result.message ?? `Response satisfies ${predicateDescription}`)\n          : (result.message ??\n            `Expected response to satisfy ${predicateDescription}`),\n    };\n  } catch (error) {\n    // Predicate threw an error\n    const errorMessage = error instanceof Error ? error.message : String(error);\n\n    return {\n      pass: this.isNot, // If using .not, an error means the predicate didn't pass\n      message: () => `Predicate threw error: ${errorMessage}`,\n    };\n  }\n}\n","/**\n * Matchers Module\n *\n * Custom Playwright matchers for MCP tool response validation.\n * These matchers use the validators internally and provide a clean\n * assertion API for Playwright tests.\n */\n\nimport { expect as baseExpect } from '@playwright/test';\n\n// Import matcher functions\nimport { toMatchToolResponse } from './toMatchToolResponse.js';\nimport { toMatchToolSchema } from './toMatchToolSchema.js';\nimport { toContainToolText } from './toContainToolText.js';\nimport { toMatchToolPattern } from './toMatchToolPattern.js';\nimport { toMatchToolSnapshot } from './toMatchToolSnapshot.js';\nimport { toBeToolError } from './toBeToolError.js';\nimport { toPassToolJudge } from './toPassToolJudge.js';\nimport { toHaveToolResponseSize } from './toHaveToolResponseSize.js';\nimport { toSatisfyToolPredicate } from './toSatisfyToolPredicate.js';\n\n// Import types for global declaration\nimport './types.js';\n\n/**\n * Extended Playwright expect with MCP tool matchers\n *\n * @example\n * ```typescript\n * import { expect } from '@mcp-testing/server-tester';\n *\n * test('weather tool', async ({ mcp }) => {\n *   const result = await mcp.callTool('get_weather', { city: 'London' });\n *\n *   expect(result).toContainToolText('temperature');\n *   expect(result).toMatchToolSchema(WeatherSchema);\n *   expect(result).not.toBeToolError();\n * });\n * ```\n */\nexport const expect = baseExpect.extend({\n  toMatchToolResponse,\n  toMatchToolSchema,\n  toContainToolText,\n  toMatchToolPattern,\n  toMatchToolSnapshot,\n  toBeToolError,\n  toPassToolJudge,\n  toHaveToolResponseSize,\n  toSatisfyToolPredicate,\n});\n\n// Re-export types\nexport type {\n  JudgeMatcherOptions,\n  ToolPredicate,\n  PredicateResult,\n} from './types.js';\n","import { test as base } from '@playwright/test';\nimport { expect } from '../assertions/matchers/index.js';\nimport type { Client } from '@modelcontextprotocol/sdk/client/index.js';\nimport type { OAuthClientProvider } from '@modelcontextprotocol/sdk/client/auth.js';\nimport {\n  createMCPClientForConfig,\n  closeMCPClient,\n} from '../mcp/clientFactory.js';\nimport {\n  createMCPFixture,\n  type MCPFixtureApi,\n  type AuthType,\n} from '../mcp/fixtures/mcpFixture.js';\nimport { PlaywrightOAuthClientProvider } from '../auth/oauthClientProvider.js';\nimport { CLIOAuthClient } from '../auth/cli.js';\nimport { isHttpConfig, type MCPConfig } from '../config/mcpConfig.js';\n\n/**\n * Internal fixture state for passing auth type between fixtures\n */\ninterface MCPFixtureState {\n  /**\n   * The resolved authentication type (may differ from config if CLI tokens are used)\n   */\n  resolvedAuthType: AuthType;\n}\n\n/**\n * Extended test fixtures for MCP testing\n */\ntype MCPFixtures = {\n  /**\n   * Raw MCP client instance (automatically connected and cleaned up)\n   */\n  mcpClient: Client;\n\n  /**\n   * High-level MCP API for tests\n   */\n  mcp: MCPFixtureApi;\n\n  /**\n   * Internal fixture state (not for external use)\n   */\n  _mcpFixtureState: MCPFixtureState;\n};\n\n/**\n * Extended Playwright test with MCP fixtures\n *\n * @example\n * import { test, expect } from '@mcp-testing/server-tester';\n *\n * test('lists tools from MCP server', async ({ mcp }) => {\n *   const tools = await mcp.listTools();\n *   expect(tools.length).toBeGreaterThan(0);\n * });\n */\nexport const test = base.extend<MCPFixtures>({\n  /**\n   * Internal fixture state - tracks resolved auth type between fixtures\n   */\n  _mcpFixtureState: [\n    // eslint-disable-next-line no-empty-pattern\n    async ({}, use) => {\n      // Initialize with 'none', will be updated by mcpClient fixture\n      const state: MCPFixtureState = { resolvedAuthType: 'none' };\n      await use(state);\n    },\n    { scope: 'test' },\n  ],\n\n  /**\n   * mcpClient fixture: Creates and connects an MCP client\n   *\n   * The client configuration is read from the project's `use.mcpConfig`\n   * setting in playwright.config.ts\n   *\n   * Authentication resolution order:\n   * 1. Explicit authStatePath → uses PlaywrightOAuthClientProvider\n   * 2. Explicit accessToken → uses static Bearer token\n   * 3. HTTP transport with no auth → tries CLI-stored tokens (from `mcp-test login`)\n   *    with automatic token refresh\n   */\n  mcpClient: async ({ _mcpFixtureState }, use, testInfo) => {\n    // Extract mcpConfig from project use settings\n    const useConfig = testInfo.project.use as { mcpConfig?: MCPConfig };\n    const mcpConfig = useConfig.mcpConfig;\n\n    if (!mcpConfig) {\n      throw new Error(\n        `Missing mcpConfig in project.use for project \"${testInfo.project.name}\". ` +\n          `Please add mcpConfig to your project configuration in playwright.config.ts`\n      );\n    }\n\n    // Track resolved auth type\n    let resolvedAuthType: AuthType = 'none';\n\n    // Create auth provider if OAuth authStatePath is configured\n    let authProvider: OAuthClientProvider | undefined;\n    if (mcpConfig.auth?.oauth?.authStatePath) {\n      authProvider = new PlaywrightOAuthClientProvider({\n        storagePath: mcpConfig.auth.oauth.authStatePath,\n        redirectUri:\n          mcpConfig.auth.oauth.redirectUri ??\n          'http://localhost:3000/oauth/callback',\n        clientId: mcpConfig.auth.oauth.clientId,\n        clientSecret: mcpConfig.auth.oauth.clientSecret,\n      });\n      resolvedAuthType = 'oauth';\n    }\n\n    // Build effective config - may add CLI tokens if no auth is configured\n    let effectiveConfig = mcpConfig;\n\n    // Check for explicit static API token\n    if (mcpConfig.auth?.accessToken) {\n      resolvedAuthType = 'api-token';\n    }\n\n    // If HTTP transport with no explicit auth, try to use CLI-stored tokens\n    // This enables the simple flow: `mcp-test login <url>` then run tests\n    if (\n      isHttpConfig(mcpConfig) &&\n      !mcpConfig.auth?.accessToken &&\n      !mcpConfig.auth?.oauth?.authStatePath\n    ) {\n      const cliClient = new CLIOAuthClient({\n        mcpServerUrl: mcpConfig.serverUrl,\n      });\n\n      // Try to get a valid token (will refresh if expired)\n      const tokenResult = await cliClient.tryGetAccessToken();\n\n      if (tokenResult) {\n        // Use the CLI token as static auth\n        effectiveConfig = {\n          ...mcpConfig,\n          auth: {\n            ...mcpConfig.auth,\n            accessToken: tokenResult.accessToken,\n          },\n        };\n        // CLI tokens come from OAuth flow\n        resolvedAuthType = 'oauth';\n      }\n    }\n\n    // Store resolved auth type for mcp fixture\n    _mcpFixtureState.resolvedAuthType = resolvedAuthType;\n\n    // Create and connect client\n    const client = await createMCPClientForConfig(effectiveConfig, {\n      clientInfo: {\n        name: '@mcp-testing/server-tester',\n        version: '0.1.0',\n      },\n      authProvider,\n    });\n\n    try {\n      // Provide client to test\n      await use(client);\n    } finally {\n      // Cleanup: close the client\n      await closeMCPClient(client);\n    }\n  },\n\n  /**\n   * mcp fixture: High-level test API built on mcpClient\n   *\n   * Depends on mcpClient fixture\n   * Automatically tracks all MCP operations for the reporter\n   */\n  mcp: async ({ mcpClient, _mcpFixtureState }, use, testInfo) => {\n    const api = createMCPFixture(mcpClient, testInfo, {\n      authType: _mcpFixtureState.resolvedAuthType,\n      project: testInfo.project.name,\n    });\n    await use(api);\n  },\n});\n\n/**\n * Re-export extended expect with MCP tool matchers\n *\n * @example\n * ```typescript\n * expect(result).toContainToolText('temperature');\n * expect(result).toMatchToolSchema(WeatherSchema);\n * expect(result).not.toBeToolError();\n * ```\n */\nexport { expect };\n","import { z } from 'zod';\nimport type { LLMHostConfig } from './llmHost/llmHostTypes.js';\nimport type { SnapshotSanitizer } from '../assertions/validators/types.js';\n\n// Re-export sanitizer types from canonical source (validators/types.ts)\n// Note: For JSON datasets, the Zod schema below validates that patterns are strings.\n// The TypeScript types allow RegExp for runtime usage with Playwright matchers.\nexport type {\n  BuiltInSanitizer,\n  SnapshotSanitizer,\n  RegexSanitizer,\n  FieldRemovalSanitizer,\n} from '../assertions/validators/types.js';\n\n/**\n * Evaluation mode\n */\nexport type EvalMode = 'direct' | 'llm_host';\n\n/**\n * A single eval test case\n *\n * For 'direct' mode: toolName and args are required\n * For 'llm_host' mode: scenario and llmHostConfig are required\n */\nexport interface EvalCase {\n  /**\n   * Unique identifier for this test case\n   */\n  id: string;\n\n  /**\n   * Human-readable description of what this test case validates\n   */\n  description?: string;\n\n  /**\n   * Evaluation mode\n   * - 'direct': Direct API calls to MCP tools (default)\n   * - 'llm_host': LLM-driven tool selection via natural language\n   *\n   * @default 'direct'\n   */\n  mode?: EvalMode;\n\n  /**\n   * Name of the MCP tool to call (required for 'direct' mode, optional for 'llm_host' mode)\n   */\n  toolName?: string;\n\n  /**\n   * Arguments to pass to the tool (required for 'direct' mode, optional for 'llm_host' mode)\n   */\n  args?: Record<string, unknown>;\n\n  /**\n   * Natural language scenario for LLM to execute (optional, required for 'llm_host' mode)\n   *\n   * @example \"Get the weather for London and tell me if I need an umbrella\"\n   */\n  scenario?: string;\n\n  /**\n   * LLM host configuration (optional for 'llm_host' mode)\n   *\n   * If not specified, uses default configuration from test environment\n   */\n  llmHostConfig?: LLMHostConfig;\n\n  /**\n   * Additional metadata for this test case\n   *\n   * For 'llm_host' mode, can include 'expectedToolCalls' for validation\n   */\n  metadata?: Record<string, unknown>;\n\n  /**\n   * Expectations to validate against the tool response\n   *\n   * Multiple expectations can be combined and will all be validated.\n   *\n   * @example\n   * ```json\n   * {\n   *   \"id\": \"weather-london\",\n   *   \"toolName\": \"get_weather\",\n   *   \"args\": { \"city\": \"London\" },\n   *   \"expect\": {\n   *     \"containsText\": [\"temperature\", \"conditions\"],\n   *     \"schema\": \"WeatherResponse\",\n   *     \"responseSize\": { \"maxBytes\": 10000 },\n   *     \"isError\": false\n   *   }\n   * }\n   * ```\n   */\n  expect?: EvalExpectBlock;\n}\n\n/**\n * Unified expectation block for eval cases\n *\n * Mirrors the Playwright matcher API for consistency.\n */\nexport interface EvalExpectBlock {\n  /**\n   * Exact response match (toMatchToolResponse)\n   */\n  response?: unknown;\n\n  /**\n   * Name of schema to validate against (toMatchToolSchema)\n   */\n  schema?: string;\n\n  /**\n   * Text substring(s) that must be present (toContainToolText)\n   */\n  containsText?: string | string[];\n\n  /**\n   * Regex pattern(s) that must match (toMatchToolPattern)\n   */\n  matchesPattern?: string | string[];\n\n  /**\n   * Snapshot name for comparison (toMatchToolSnapshot)\n   */\n  snapshot?: string;\n\n  /**\n   * Snapshot sanitizers to apply\n   */\n  snapshotSanitizers?: SnapshotSanitizer[];\n\n  /**\n   * Error expectation (toBeToolError)\n   * - true: expects any error\n   * - false: expects no error\n   * - string: expects error containing this message\n   */\n  isError?: boolean | string | string[];\n\n  /**\n   * LLM-as-judge evaluation (toPassToolJudge)\n   */\n  passesJudge?: {\n    /** Evaluation rubric/criteria */\n    rubric: string;\n    /** Reference response to compare against */\n    reference?: unknown;\n    /** Score threshold for passing (0-1, default: 0.7) */\n    threshold?: number;\n    /** Judge configuration ID */\n    configId?: string;\n  };\n\n  /**\n   * Response size validation (toHaveToolResponseSize)\n   */\n  responseSize?: {\n    /** Maximum allowed size in bytes */\n    maxBytes?: number;\n    /** Minimum required size in bytes */\n    minBytes?: number;\n  };\n}\n\n/**\n * A complete eval dataset containing multiple test cases\n */\nexport interface EvalDataset {\n  /**\n   * Dataset name\n   */\n  name: string;\n\n  /**\n   * Dataset description\n   */\n  description?: string;\n\n  /**\n   * Test cases in this dataset\n   */\n  cases: Array<EvalCase>;\n\n  /**\n   * Optional schema definitions referenced by test cases\n   */\n  schemas?: Record<string, z.ZodSchema>;\n\n  /**\n   * Additional dataset metadata\n   */\n  metadata?: Record<string, unknown>;\n}\n\n/**\n * Zod schema for LLMHostConfig (simplified for serialization)\n */\nconst LLMHostConfigSchema = z.object({\n  provider: z.enum(['openai', 'anthropic']),\n  apiKeyEnvVar: z.string().optional(),\n  model: z.string().optional(),\n  maxTokens: z.number().optional(),\n  temperature: z.number().optional(),\n  maxToolCalls: z.number().optional(),\n});\n\n/**\n * Zod schema for SnapshotSanitizer\n */\nconst SnapshotSanitizerSchema = z.union([\n  // Built-in sanitizers\n  z.enum(['timestamp', 'uuid', 'iso-date', 'objectId', 'jwt']),\n  // Custom regex sanitizer\n  z.object({\n    pattern: z.string(),\n    replacement: z.string().optional(),\n  }),\n  // Field removal sanitizer\n  z.object({\n    remove: z.array(z.string()),\n  }),\n]);\n\n/**\n * Zod schema for EvalExpectBlock\n */\nconst EvalExpectBlockSchema = z.object({\n  response: z.unknown().optional(),\n  schema: z.string().optional(),\n  containsText: z.union([z.string(), z.array(z.string())]).optional(),\n  matchesPattern: z.union([z.string(), z.array(z.string())]).optional(),\n  snapshot: z.string().optional(),\n  snapshotSanitizers: z.array(SnapshotSanitizerSchema).optional(),\n  isError: z.union([z.boolean(), z.string(), z.array(z.string())]).optional(),\n  passesJudge: z\n    .object({\n      rubric: z.string(),\n      reference: z.unknown().optional(),\n      threshold: z.number().min(0).max(1).optional(),\n      configId: z.string().optional(),\n    })\n    .optional(),\n  responseSize: z\n    .object({\n      maxBytes: z.number().optional(),\n      minBytes: z.number().optional(),\n    })\n    .optional(),\n});\n\n/**\n * Zod schema for EvalCase\n *\n * toolName and args are optional for llm_host mode (which uses scenario instead)\n */\nexport const EvalCaseSchema = z.object({\n  id: z.string().min(1, 'id must not be empty'),\n  description: z.string().optional(),\n  mode: z.enum(['direct', 'llm_host']).optional(),\n  toolName: z.string().min(1, 'toolName must not be empty').optional(),\n  args: z.record(z.unknown()).optional(),\n  scenario: z.string().optional(),\n  llmHostConfig: LLMHostConfigSchema.optional(),\n  metadata: z.record(z.unknown()).optional(),\n  expect: EvalExpectBlockSchema.optional(),\n});\n\n/**\n * Zod schema for EvalDataset (without schemas field, as schemas aren't serializable)\n */\nexport const EvalDatasetSchema = z.object({\n  name: z.string().min(1, 'name must not be empty'),\n  description: z.string().optional(),\n  cases: z.array(EvalCaseSchema).min(1, 'dataset must have at least one case'),\n  metadata: z.record(z.unknown()).optional(),\n});\n\n/**\n * Type for serialized eval dataset (without Zod schemas)\n */\nexport type SerializedEvalDataset = z.infer<typeof EvalDatasetSchema>;\n\n/**\n * Validates an eval case\n *\n * @param evalCase - The eval case to validate\n * @returns The validated eval case\n * @throws {z.ZodError} If validation fails\n */\nexport function validateEvalCase(evalCase: unknown): EvalCase {\n  return EvalCaseSchema.parse(evalCase);\n}\n\n/**\n * Validates a serialized eval dataset\n *\n * @param dataset - The dataset to validate\n * @returns The validated dataset\n * @throws {z.ZodError} If validation fails\n */\nexport function validateEvalDataset(dataset: unknown): SerializedEvalDataset {\n  return EvalDatasetSchema.parse(dataset);\n}\n","import { readFile } from 'fs/promises';\nimport { type z } from 'zod';\nimport {\n  type EvalDataset,\n  type SerializedEvalDataset,\n  validateEvalDataset,\n} from './datasetTypes.js';\n\n/**\n * Options for loading an eval dataset\n */\nexport interface LoadDatasetOptions {\n  /**\n   * Optional schema definitions to attach to the dataset\n   *\n   * Keys should match the expectedSchemaName in eval cases\n   */\n  schemas?: Record<string, z.ZodSchema>;\n\n  /**\n   * Whether to validate the loaded dataset\n   * @default true\n   */\n  validate?: boolean;\n}\n\n/**\n * Loads an eval dataset from a JSON file\n *\n * @param filePath - Absolute path to the JSON file\n * @param options - Load options\n * @returns The loaded and validated dataset\n * @throws {Error} If file cannot be read or JSON is invalid\n * @throws {z.ZodError} If validation fails\n *\n * @example\n * const dataset = await loadEvalDataset('./data/my-evals.json', {\n *   schemas: {\n *     'weather-response': WeatherResponseSchema,\n *   },\n * });\n */\nexport async function loadEvalDataset(\n  filePath: string,\n  options: LoadDatasetOptions = {}\n): Promise<EvalDataset> {\n  const { schemas, validate = true } = options;\n\n  try {\n    const fileContents = await readFile(filePath, 'utf-8');\n    const rawData: unknown = JSON.parse(fileContents);\n\n    // Validate if requested\n    const serializedDataset: SerializedEvalDataset = validate\n      ? validateEvalDataset(rawData)\n      : (rawData as SerializedEvalDataset);\n\n    // Create full dataset with schemas\n    const dataset: EvalDataset = {\n      ...serializedDataset,\n      schemas: schemas ?? {},\n    };\n\n    return dataset;\n  } catch (error) {\n    if (error instanceof SyntaxError) {\n      throw new Error(\n        `Failed to parse JSON from ${filePath}: ${error.message}`\n      );\n    }\n    throw error;\n  }\n}\n\n/**\n * Loads an eval dataset from a plain object\n *\n * Useful for programmatically creating datasets in tests\n *\n * @param data - The dataset data\n * @param options - Load options\n * @returns The loaded and validated dataset\n * @throws {z.ZodError} If validation fails\n *\n * @example\n * const dataset = loadEvalDatasetFromObject({\n *   name: 'my-test-dataset',\n *   cases: [\n *     {\n *       id: 'case-1',\n *       toolName: 'get_weather',\n *       args: { city: 'London' },\n *     },\n *   ],\n * });\n */\nexport function loadEvalDatasetFromObject(\n  data: unknown,\n  options: LoadDatasetOptions = {}\n): EvalDataset {\n  const { schemas, validate = true } = options;\n\n  // Validate if requested\n  const serializedDataset: SerializedEvalDataset = validate\n    ? validateEvalDataset(data)\n    : (data as SerializedEvalDataset);\n\n  // Create full dataset with schemas\n  const dataset: EvalDataset = {\n    ...serializedDataset,\n    schemas: schemas ?? {},\n  };\n\n  return dataset;\n}\n","/**\n * LLM Adapter Interface\n *\n * Defines the contract for LLM provider adapters, enabling\n * the orchestrator to work with any LLM provider through\n * a unified interface.\n */\n\nimport type { Tool } from '@modelcontextprotocol/sdk/types.js';\nimport type {\n  LLMProvider,\n  LLMToolCall,\n  LLMHostConfig,\n} from './llmHostTypes.js';\n\n/**\n * Result from an LLM chat call\n */\nexport interface LLMChatResult {\n  /**\n   * Whether the LLM wants to call tools\n   */\n  wantsToolCalls: boolean;\n\n  /**\n   * Tool calls requested by the LLM (if any)\n   */\n  toolCalls: LLMToolCall[];\n\n  /**\n   * Text content from the response (final answer if no tool calls)\n   */\n  textContent: string | null;\n\n  /**\n   * Raw response from the LLM (for debugging)\n   */\n  rawResponse: unknown;\n}\n\n/**\n * LLM Adapter interface\n *\n * Each provider (OpenAI, Anthropic) implements this interface\n * to normalize their specific APIs into a common format.\n */\nexport interface LLMAdapter {\n  /**\n   * Provider identifier\n   */\n  readonly provider: LLMProvider;\n\n  /**\n   * Loads the SDK and creates a client\n   *\n   * @param config - LLM host configuration\n   * @returns Configured client instance\n   * @throws Error if SDK not installed or API key missing\n   */\n  createClient(config: LLMHostConfig): Promise<unknown>;\n\n  /**\n   * Converts MCP tools to the provider's tool format\n   *\n   * @param tools - MCP tool definitions\n   * @returns Tools in provider-specific format\n   */\n  formatTools(tools: Tool[]): unknown[];\n\n  /**\n   * Makes a chat completion request with tool support\n   *\n   * @param client - Client from createClient()\n   * @param messages - Conversation history in provider format\n   * @param tools - Formatted tools from formatTools()\n   * @param config - LLM configuration (model, temperature, etc.)\n   * @returns Chat result with parsed tool calls or text response\n   */\n  chat(\n    client: unknown,\n    messages: unknown[],\n    tools: unknown[],\n    config: LLMHostConfig\n  ): Promise<LLMChatResult>;\n\n  /**\n   * Creates the initial message for a scenario\n   *\n   * @param scenario - User's natural language prompt\n   * @returns Initial message in provider format\n   */\n  createUserMessage(scenario: string): unknown;\n\n  /**\n   * Creates an assistant message with tool calls\n   *\n   * @param chatResult - Result from chat() that had tool calls\n   * @returns Assistant message in provider format\n   */\n  createAssistantMessage(chatResult: LLMChatResult): unknown;\n\n  /**\n   * Creates tool result messages\n   *\n   * @param toolCall - The tool call that was executed\n   * @param result - Text result from MCP tool execution\n   * @returns Tool result message(s) in provider format\n   */\n  createToolResultMessage(toolCall: LLMToolCall, result: string): unknown;\n}\n\n/**\n * Registry of available adapters\n */\nexport type AdapterFactory = () => LLMAdapter;\n\nconst adapters = new Map<LLMProvider, AdapterFactory>();\n\n/**\n * Registers an adapter factory for a provider\n */\nexport function registerAdapter(\n  provider: LLMProvider,\n  factory: AdapterFactory\n): void {\n  adapters.set(provider, factory);\n}\n\n/**\n * Gets an adapter for a provider\n *\n * @param provider - LLM provider\n * @returns Adapter instance\n * @throws Error if provider not registered\n */\nexport function getAdapter(provider: LLMProvider): LLMAdapter {\n  const factory = adapters.get(provider);\n  if (!factory) {\n    throw new Error(\n      `No adapter registered for provider: ${provider}. Available: ${Array.from(adapters.keys()).join(', ')}`\n    );\n  }\n  return factory();\n}\n\n/**\n * Checks if an adapter is registered for a provider\n */\nexport function hasAdapter(provider: LLMProvider): boolean {\n  return adapters.has(provider);\n}\n","/**\n * Retry utility with exponential backoff for LLM API calls\n */\n\n/**\n * Options for retry behavior\n */\nexport interface RetryOptions {\n  /**\n   * Maximum number of attempts (including the first)\n   * @default 3\n   */\n  maxAttempts?: number;\n\n  /**\n   * Base delay in milliseconds before first retry\n   * @default 1000\n   */\n  baseDelayMs?: number;\n\n  /**\n   * Maximum delay in milliseconds\n   * @default 30000\n   */\n  maxDelayMs?: number;\n\n  /**\n   * Function to determine if an error is retryable\n   * @default Retries on 429, 500, 502, 503, 504 HTTP errors\n   */\n  isRetryable?: (error: unknown) => boolean;\n\n  /**\n   * Callback invoked before each retry\n   */\n  onRetry?: (error: unknown, attempt: number, delayMs: number) => void;\n}\n\n/**\n * Default retry options\n */\nconst DEFAULT_OPTIONS: Required<Omit<RetryOptions, 'onRetry'>> & {\n  onRetry?: RetryOptions['onRetry'];\n} = {\n  maxAttempts: 3,\n  baseDelayMs: 1000,\n  maxDelayMs: 30000,\n  isRetryable: isRetryableError,\n};\n\n/**\n * Executes a function with retry logic and exponential backoff\n *\n * @param fn - Async function to execute\n * @param options - Retry options\n * @returns Result of the function\n * @throws Last error if all retries fail\n *\n * @example\n * ```typescript\n * const result = await withRetry(\n *   () => openai.chat.completions.create({ ... }),\n *   { maxAttempts: 3, baseDelayMs: 1000 }\n * );\n * ```\n */\nexport async function withRetry<T>(\n  fn: () => Promise<T>,\n  options: RetryOptions = {}\n): Promise<T> {\n  const {\n    maxAttempts = DEFAULT_OPTIONS.maxAttempts,\n    baseDelayMs = DEFAULT_OPTIONS.baseDelayMs,\n    maxDelayMs = DEFAULT_OPTIONS.maxDelayMs,\n    isRetryable = DEFAULT_OPTIONS.isRetryable,\n    onRetry,\n  } = options;\n\n  let lastError: unknown;\n\n  for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n    try {\n      return await fn();\n    } catch (error) {\n      lastError = error;\n\n      // Don't retry if it's the last attempt or error isn't retryable\n      if (attempt >= maxAttempts || !isRetryable(error)) {\n        throw error;\n      }\n\n      // Calculate delay with exponential backoff and jitter\n      const exponentialDelay = baseDelayMs * Math.pow(2, attempt - 1);\n      const jitter = Math.random() * 0.1 * exponentialDelay; // 10% jitter\n      const delayMs = Math.min(exponentialDelay + jitter, maxDelayMs);\n\n      // Notify before retry\n      if (onRetry) {\n        onRetry(error, attempt, delayMs);\n      }\n\n      // Wait before retrying\n      await sleep(delayMs);\n    }\n  }\n\n  // Should never reach here, but TypeScript needs it\n  throw lastError;\n}\n\n/**\n * Determines if an error is retryable based on HTTP status codes\n *\n * Retries on:\n * - 429 Too Many Requests (rate limit)\n * - 500 Internal Server Error\n * - 502 Bad Gateway\n * - 503 Service Unavailable\n * - 504 Gateway Timeout\n */\nexport function isRetryableError(error: unknown): boolean {\n  // Check for HTTP status code in various error formats\n  const statusCode = extractStatusCode(error);\n\n  if (statusCode !== null) {\n    return [429, 500, 502, 503, 504].includes(statusCode);\n  }\n\n  // Check error message for common retryable patterns\n  const message = extractErrorMessage(error).toLowerCase();\n  return (\n    message.includes('rate limit') ||\n    message.includes('429') ||\n    message.includes('too many requests') ||\n    message.includes('timeout') ||\n    message.includes('temporarily unavailable') ||\n    message.includes('service unavailable') ||\n    message.includes('internal server error')\n  );\n}\n\n/**\n * Extracts HTTP status code from various error formats\n */\nfunction extractStatusCode(error: unknown): number | null {\n  if (error == null || typeof error !== 'object') {\n    return null;\n  }\n\n  const e = error as Record<string, unknown>;\n\n  // Direct status property\n  if (typeof e.status === 'number') {\n    return e.status;\n  }\n\n  // statusCode property\n  if (typeof e.statusCode === 'number') {\n    return e.statusCode;\n  }\n\n  // response.status (Axios-style)\n  if (e.response && typeof e.response === 'object') {\n    const response = e.response as Record<string, unknown>;\n    if (typeof response.status === 'number') {\n      return response.status;\n    }\n  }\n\n  // code property (some SDKs use this)\n  if (typeof e.code === 'number') {\n    return e.code;\n  }\n\n  return null;\n}\n\n/**\n * Extracts error message from various error formats\n */\nfunction extractErrorMessage(error: unknown): string {\n  if (error == null) {\n    return '';\n  }\n\n  if (typeof error === 'string') {\n    return error;\n  }\n\n  if (error instanceof Error) {\n    return error.message;\n  }\n\n  if (typeof error === 'object') {\n    const e = error as Record<string, unknown>;\n    if (typeof e.message === 'string') {\n      return e.message;\n    }\n    if (typeof e.error === 'string') {\n      return e.error;\n    }\n    // Fallback to JSON for unknown object shapes\n    return JSON.stringify(error);\n  }\n\n  // Primitives (number, boolean)\n  if (typeof error === 'number' || typeof error === 'boolean') {\n    return String(error);\n  }\n\n  return 'Unknown error';\n}\n\n/**\n * Sleep for a given number of milliseconds\n */\nfunction sleep(ms: number): Promise<void> {\n  return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","/**\n * LLM Host Simulation Orchestrator\n *\n * Implements the shared agentic loop logic that works with any LLM adapter.\n * This is the core of the simulation - it handles tool execution, conversation\n * management, and retry logic.\n */\n\nimport type { MCPFixtureApi } from '../../mcp/fixtures/mcpFixture.js';\nimport { extractText } from '../../mcp/response.js';\nimport type { LLMAdapter } from './adapter.js';\nimport type {\n  LLMHostConfig,\n  LLMHostSimulationResult,\n  LLMToolCall,\n} from './llmHostTypes.js';\nimport { withRetry, type RetryOptions } from './retry.js';\n\n/**\n * Options for the simulation orchestrator\n */\nexport interface OrchestratorOptions {\n  /**\n   * Retry options for LLM API calls\n   */\n  retry?: RetryOptions;\n}\n\n/**\n * Runs an LLM host simulation using the provided adapter\n *\n * This function implements the agentic loop:\n * 1. Send scenario to LLM with available tools\n * 2. If LLM wants to call tools, execute them via MCP\n * 3. Add tool results to conversation and repeat\n * 4. When LLM gives final response, return results\n *\n * @param adapter - LLM adapter (OpenAI, Anthropic, etc.)\n * @param mcp - MCP fixture API for tool execution\n * @param scenario - Natural language prompt\n * @param config - LLM host configuration\n * @param options - Orchestrator options (retry, etc.)\n * @returns Simulation result with tool calls and response\n */\nexport async function runSimulation(\n  adapter: LLMAdapter,\n  mcp: MCPFixtureApi,\n  scenario: string,\n  config: LLMHostConfig,\n  options: OrchestratorOptions = {}\n): Promise<LLMHostSimulationResult> {\n  const maxIterations = config.maxToolCalls || 10;\n  const retryOptions = options.retry || {};\n\n  // Track all tool calls\n  const allToolCalls: LLMToolCall[] = [];\n\n  // Track conversation history for debugging\n  const conversationHistory: Array<{\n    role: 'user' | 'assistant' | 'tool';\n    content: string;\n  }> = [];\n\n  try {\n    // Create LLM client\n    const client = await adapter.createClient(config);\n\n    // Get tools from MCP server and format for LLM\n    const mcpTools = await mcp.listTools();\n    const formattedTools = adapter.formatTools(mcpTools);\n\n    // Initialize conversation with user message\n    const messages: unknown[] = [adapter.createUserMessage(scenario)];\n    conversationHistory.push({ role: 'user', content: scenario });\n\n    let finalResponse = '';\n\n    // Agentic loop\n    for (let iteration = 0; iteration < maxIterations; iteration++) {\n      // Call LLM with retry\n      const chatResult = await withRetry(\n        () => adapter.chat(client, messages, formattedTools, config),\n        retryOptions\n      );\n\n      // Check if LLM wants to call tools\n      if (chatResult.wantsToolCalls && chatResult.toolCalls.length > 0) {\n        // Add assistant message to conversation\n        messages.push(adapter.createAssistantMessage(chatResult));\n\n        // Execute each tool call through MCP\n        const toolResultMessages: unknown[] = [];\n\n        for (const toolCall of chatResult.toolCalls) {\n          // Track the tool call\n          allToolCalls.push(toolCall);\n\n          // Execute via MCP\n          const mcpResult = await mcp.callTool(\n            toolCall.name,\n            toolCall.arguments\n          );\n\n          // Extract text from MCP response\n          const resultText = extractText(mcpResult);\n\n          // Create tool result message\n          const resultMessage = adapter.createToolResultMessage(\n            toolCall,\n            resultText\n          );\n          toolResultMessages.push(resultMessage);\n\n          // Track in conversation history\n          conversationHistory.push({ role: 'tool', content: resultText });\n        }\n\n        // Add tool results to conversation\n        // Note: Anthropic wraps tool results in a user message, OpenAI adds them directly\n        if (adapter.provider === 'anthropic') {\n          messages.push({\n            role: 'user',\n            content: toolResultMessages,\n          });\n        } else {\n          // OpenAI: add each tool result as a separate message\n          for (const msg of toolResultMessages) {\n            messages.push(msg);\n          }\n        }\n      } else {\n        // No tool calls - we have the final response\n        finalResponse = chatResult.textContent || '';\n        conversationHistory.push({ role: 'assistant', content: finalResponse });\n        break;\n      }\n    }\n\n    return {\n      success: true,\n      toolCalls: allToolCalls,\n      response: finalResponse,\n      conversationHistory,\n    };\n  } catch (error) {\n    return {\n      success: false,\n      toolCalls: allToolCalls,\n      error: error instanceof Error ? error.message : String(error),\n      conversationHistory,\n    };\n  }\n}\n","/**\n * OpenAI Adapter for LLM Host Simulation\n *\n * Implements the LLMAdapter interface for OpenAI's Chat Completions API.\n */\n\nimport type { Tool } from '@modelcontextprotocol/sdk/types.js';\nimport type { LLMAdapter, LLMChatResult } from '../adapter.js';\nimport type { LLMHostConfig, LLMToolCall } from '../llmHostTypes.js';\n\n/**\n * OpenAI-specific types (minimal to avoid full SDK dependency at compile time)\n */\ninterface OpenAITool {\n  type: 'function';\n  function: {\n    name: string;\n    description: string;\n    parameters: Record<string, unknown>;\n  };\n}\n\ninterface OpenAIMessage {\n  role: 'user' | 'assistant' | 'tool' | 'system';\n  content: string | null;\n  tool_calls?: Array<{\n    id: string;\n    type: 'function';\n    function: {\n      name: string;\n      arguments: string;\n    };\n  }>;\n  tool_call_id?: string;\n}\n\n/**\n * Creates an OpenAI adapter\n */\nexport function createOpenAIAdapter(): LLMAdapter {\n  return {\n    provider: 'openai',\n\n    async createClient(config: LLMHostConfig): Promise<unknown> {\n      // Dynamic import for optional dependency\n      // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n      let OpenAI;\n      try {\n        // @ts-expect-error - Optional dependency, dynamically imported\n        // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n        const module = await import('openai');\n        // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access\n        OpenAI = module.OpenAI;\n      } catch {\n        throw new Error(\n          'OpenAI SDK is not installed. Install it with: npm install openai'\n        );\n      }\n\n      // Get API key\n      const apiKeyEnvVar = config.apiKeyEnvVar || 'OPENAI_API_KEY';\n      const apiKey = process.env[apiKeyEnvVar];\n\n      if (!apiKey) {\n        throw new Error(\n          `OpenAI API key not found in environment variable ${apiKeyEnvVar}`\n        );\n      }\n\n      // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n      return new OpenAI({ apiKey });\n    },\n\n    formatTools(tools: Tool[]): OpenAITool[] {\n      return tools.map((tool) => ({\n        type: 'function' as const,\n        function: {\n          name: tool.name,\n          description: tool.description || '',\n          parameters: (tool.inputSchema as Record<string, unknown>) || {},\n        },\n      }));\n    },\n\n    async chat(\n      client: unknown,\n      messages: unknown[],\n      tools: unknown[],\n      config: LLMHostConfig\n    ): Promise<LLMChatResult> {\n      const openai = client as {\n        chat: { completions: { create: (opts: unknown) => Promise<unknown> } };\n      };\n\n      const response = await openai.chat.completions.create({\n        model: config.model || 'gpt-4o',\n        messages: messages as OpenAIMessage[],\n        tools: tools as OpenAITool[],\n        temperature: config.temperature ?? 0.0,\n        max_tokens: config.maxTokens,\n      });\n\n      // Parse response\n      const resp = response as {\n        choices: Array<{\n          message: {\n            content: string | null;\n            tool_calls?: Array<{\n              id: string;\n              type: string;\n              function: {\n                name: string;\n                arguments: string;\n              };\n            }>;\n          };\n        }>;\n      };\n\n      const message = resp.choices[0]?.message;\n      if (!message) {\n        throw new Error('No response from OpenAI');\n      }\n\n      // Check for tool calls\n      if (message.tool_calls && message.tool_calls.length > 0) {\n        const toolCalls: LLMToolCall[] = message.tool_calls.map((tc) => ({\n          name: tc.function.name,\n          arguments: JSON.parse(tc.function.arguments) as Record<\n            string,\n            unknown\n          >,\n          id: tc.id,\n        }));\n\n        return {\n          wantsToolCalls: true,\n          toolCalls,\n          textContent: message.content,\n          rawResponse: response,\n        };\n      }\n\n      // No tool calls - final response\n      return {\n        wantsToolCalls: false,\n        toolCalls: [],\n        textContent: message.content,\n        rawResponse: response,\n      };\n    },\n\n    createUserMessage(scenario: string): OpenAIMessage {\n      return {\n        role: 'user',\n        content: scenario,\n      };\n    },\n\n    createAssistantMessage(chatResult: LLMChatResult): OpenAIMessage {\n      const rawResponse = chatResult.rawResponse as {\n        choices: Array<{ message: { tool_calls?: unknown[] } }>;\n      };\n\n      return {\n        role: 'assistant',\n        content: chatResult.textContent,\n        tool_calls: rawResponse.choices[0]?.message\n          ?.tool_calls as OpenAIMessage['tool_calls'],\n      };\n    },\n\n    createToolResultMessage(\n      toolCall: LLMToolCall,\n      result: string\n    ): OpenAIMessage {\n      return {\n        role: 'tool',\n        tool_call_id: toolCall.id,\n        content: result,\n      };\n    },\n  };\n}\n","/**\n * Anthropic Adapter for LLM Host Simulation\n *\n * Implements the LLMAdapter interface for Anthropic's Messages API.\n */\n\nimport type { Tool } from '@modelcontextprotocol/sdk/types.js';\nimport type { LLMAdapter, LLMChatResult } from '../adapter.js';\nimport type { LLMHostConfig, LLMToolCall } from '../llmHostTypes.js';\n\n/**\n * Anthropic-specific types (minimal to avoid full SDK dependency at compile time)\n */\ninterface AnthropicTool {\n  name: string;\n  description: string;\n  input_schema: Record<string, unknown>;\n}\n\ninterface AnthropicMessage {\n  role: 'user' | 'assistant';\n  content: string | AnthropicContentBlock[];\n}\n\ninterface AnthropicContentBlock {\n  type: 'text' | 'tool_use' | 'tool_result';\n  text?: string;\n  id?: string;\n  name?: string;\n  input?: Record<string, unknown>;\n  tool_use_id?: string;\n  content?: string;\n}\n\n/**\n * Creates an Anthropic adapter\n */\nexport function createAnthropicAdapter(): LLMAdapter {\n  return {\n    provider: 'anthropic',\n\n    async createClient(config: LLMHostConfig): Promise<unknown> {\n      // Dynamic import for optional dependency\n      // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n      let Anthropic;\n      try {\n        // @ts-expect-error - Optional dependency, dynamically imported\n        // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n        const module = await import('@anthropic-ai/sdk');\n        // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access\n        Anthropic = module.default;\n      } catch {\n        throw new Error(\n          'Anthropic SDK is not installed. Install it with: npm install @anthropic-ai/sdk'\n        );\n      }\n\n      // Get API key\n      const apiKeyEnvVar = config.apiKeyEnvVar || 'ANTHROPIC_API_KEY';\n      const apiKey = process.env[apiKeyEnvVar];\n\n      if (!apiKey) {\n        throw new Error(\n          `Anthropic API key not found in environment variable ${apiKeyEnvVar}`\n        );\n      }\n\n      // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n      return new Anthropic({ apiKey });\n    },\n\n    formatTools(tools: Tool[]): AnthropicTool[] {\n      return tools.map((tool) => ({\n        name: tool.name,\n        description: tool.description || '',\n        input_schema: (tool.inputSchema as Record<string, unknown>) || {},\n      }));\n    },\n\n    async chat(\n      client: unknown,\n      messages: unknown[],\n      tools: unknown[],\n      config: LLMHostConfig\n    ): Promise<LLMChatResult> {\n      const anthropic = client as {\n        messages: { create: (opts: unknown) => Promise<unknown> };\n      };\n\n      const response = await anthropic.messages.create({\n        model: config.model || 'claude-3-5-sonnet-20241022',\n        max_tokens: config.maxTokens || 4096,\n        temperature: config.temperature ?? 0.0,\n        messages: messages as AnthropicMessage[],\n        tools: tools as AnthropicTool[],\n      });\n\n      // Parse response\n      const resp = response as {\n        stop_reason: string;\n        content: AnthropicContentBlock[];\n      };\n\n      // Extract text content\n      const textBlock = resp.content.find((c) => c.type === 'text');\n      const textContent = textBlock?.text || null;\n\n      // Check stop reason\n      if (resp.stop_reason === 'tool_use') {\n        // Extract tool uses\n        const toolUses = resp.content.filter((c) => c.type === 'tool_use');\n        const toolCalls: LLMToolCall[] = toolUses.map((tu) => ({\n          name: tu.name!,\n          arguments: tu.input as Record<string, unknown>,\n          id: tu.id,\n        }));\n\n        return {\n          wantsToolCalls: true,\n          toolCalls,\n          textContent,\n          rawResponse: response,\n        };\n      }\n\n      if (resp.stop_reason === 'max_tokens') {\n        throw new Error('Response exceeded max tokens');\n      }\n\n      // No tool calls - final response (end_turn or other)\n      return {\n        wantsToolCalls: false,\n        toolCalls: [],\n        textContent,\n        rawResponse: response,\n      };\n    },\n\n    createUserMessage(scenario: string): AnthropicMessage {\n      return {\n        role: 'user',\n        content: scenario,\n      };\n    },\n\n    createAssistantMessage(chatResult: LLMChatResult): AnthropicMessage {\n      const rawResponse = chatResult.rawResponse as {\n        content: AnthropicContentBlock[];\n      };\n\n      return {\n        role: 'assistant',\n        content: rawResponse.content,\n      };\n    },\n\n    createToolResultMessage(\n      toolCall: LLMToolCall,\n      result: string\n    ): AnthropicContentBlock {\n      return {\n        type: 'tool_result',\n        tool_use_id: toolCall.id,\n        content: result,\n      };\n    },\n  };\n}\n","/**\n * LLM Host Simulation - Main entry point\n *\n * Provides the public API for simulating LLM hosts interacting\n * with MCP servers through actual LLM providers.\n */\n\nimport type { MCPFixtureApi } from '../../mcp/fixtures/mcpFixture.js';\nimport type {\n  LLMHostConfig,\n  LLMHostSimulationResult,\n  LLMProvider,\n} from './llmHostTypes.js';\nimport { registerAdapter, getAdapter, hasAdapter } from './adapter.js';\nimport { runSimulation } from './orchestrator.js';\nimport { createOpenAIAdapter } from './adapters/openai.js';\nimport { createAnthropicAdapter } from './adapters/anthropic.js';\n\n// Register built-in adapters\nregisterAdapter('openai', createOpenAIAdapter);\nregisterAdapter('anthropic', createAnthropicAdapter);\n\n/**\n * Simulates an LLM host interacting with an MCP server\n *\n * This function uses actual LLM providers (OpenAI or Anthropic) to test\n * MCP servers through natural language scenarios. The LLM chooses which\n * tools to call based on their descriptions, testing discoverability and\n * parameter clarity.\n *\n * @param mcp - MCP fixture API\n * @param scenario - Natural language prompt describing what to do\n * @param config - LLM host configuration\n * @returns Simulation result with tool calls and final response\n *\n * @example\n * ```typescript\n * const result = await simulateLLMHost(mcp,\n *   \"Get the weather for London\",\n *   {\n *     provider: 'openai',\n *     model: 'gpt-4o'\n *   }\n * );\n *\n * expect(result.success).toBe(true);\n * expect(result.toolCalls).toContainEqual({\n *   name: 'get_weather',\n *   arguments: { city: 'London' }\n * });\n * ```\n */\nexport async function simulateLLMHost(\n  mcp: MCPFixtureApi,\n  scenario: string,\n  config: LLMHostConfig\n): Promise<LLMHostSimulationResult> {\n  const adapter = getAdapter(config.provider);\n\n  return runSimulation(adapter, mcp, scenario, config, {\n    retry: {\n      maxAttempts: 3,\n      baseDelayMs: 1000,\n      maxDelayMs: 30000,\n    },\n  });\n}\n\n/**\n * Checks if the required SDK is available for a given provider\n *\n * This performs a quick check without actually loading the SDK.\n * The actual SDK loading happens in the adapter when simulation runs.\n *\n * @param provider - LLM provider to check\n * @returns true if an adapter is registered for the provider\n */\nexport function isProviderAvailable(provider: LLMProvider): boolean {\n  return hasAdapter(provider);\n}\n\n/**\n * Gets a helpful error message for missing dependencies\n *\n * @param provider - LLM provider\n * @returns Error message with installation instructions\n */\nexport function getMissingDependencyMessage(provider: LLMProvider): string {\n  switch (provider) {\n    case 'openai':\n      return 'OpenAI SDK is not installed. Install it with: npm install openai';\n    case 'anthropic':\n      return 'Anthropic SDK is not installed. Install it with: npm install @anthropic-ai/sdk';\n    default:\n      return `Unknown provider: ${String(provider)}`;\n  }\n}\n\n// Re-export adapter utilities for advanced usage\nexport { registerAdapter, getAdapter, hasAdapter } from './adapter.js';\nexport { runSimulation } from './orchestrator.js';\nexport { withRetry, isRetryableError, type RetryOptions } from './retry.js';\nexport type { LLMAdapter, LLMChatResult } from './adapter.js';\n","import type { MCPFixtureApi } from '../mcp/fixtures/mcpFixture.js';\nimport type { JudgeConfig } from '../judge/judgeTypes.js';\nimport type { EvalDataset, EvalCase, EvalExpectBlock } from './datasetTypes.js';\nimport type { TestInfo, Expect } from '@playwright/test';\nimport type { ZodType } from 'zod';\nimport { simulateLLMHost } from './llmHost/llmHostSimulation.js';\nimport type {\n  AuthType,\n  ResultSource,\n  ExpectationType,\n  EvalExpectationResult,\n} from '../types/index.js';\nimport {\n  validateResponse,\n  validateSchema,\n  validateText,\n  validatePattern,\n  validateError,\n  validateSize,\n} from '../assertions/validators/index.js';\nimport { createJudge } from '../judge/judgeClient.js';\n\n/**\n * Context passed to the eval runner\n */\nexport interface EvalContext {\n  /**\n   * MCP fixture API for interacting with the server\n   */\n  mcp: MCPFixtureApi;\n\n  /**\n   * Optional Playwright TestInfo for reporter integration\n   * When provided, eval results will be attached to the test for the MCP reporter\n   */\n  testInfo?: TestInfo;\n\n  /**\n   * Optional Playwright expect function for snapshot testing\n   * Required for snapshot expectations to work properly\n   */\n  expect?: Expect;\n}\n\nexport type { EvalExpectationResult } from '../types/index.js';\n\n/**\n * Result of a single eval case\n */\nexport interface EvalCaseResult {\n  /**\n   * Case ID\n   */\n  id: string;\n\n  /**\n   * Dataset name this case belongs to\n   */\n  datasetName: string;\n\n  /**\n   * MCP tool name that was called\n   */\n  toolName: string;\n\n  /**\n   * Evaluation mode (direct or llm_host)\n   * @deprecated Mode is inferred from test context, not displayed in reports\n   */\n  mode?: 'direct' | 'llm_host';\n\n  /**\n   * Source of this result\n   * - 'eval': From runEvalDataset() using JSON eval datasets\n   * - 'test': From direct API test tracking (MCP fixture calls)\n   */\n  source: ResultSource;\n\n  /**\n   * Overall pass/fail status\n   */\n  pass: boolean;\n\n  /**\n   * Tool response\n   */\n  response?: unknown;\n\n  /**\n   * Error if tool call failed\n   */\n  error?: string;\n\n  /**\n   * Expectation results\n   */\n  expectations: Partial<Record<ExpectationType, EvalExpectationResult>>;\n\n  /**\n   * Authentication type used for this test\n   */\n  authType?: AuthType;\n\n  /**\n   * Playwright project name this test belongs to\n   * Used for filtering/grouping results by project in the reporter\n   */\n  project?: string;\n\n  /**\n   * Execution time in milliseconds\n   */\n  durationMs: number;\n}\n\n/**\n * Overall result of running an eval dataset\n */\nexport interface EvalRunnerResult {\n  /**\n   * Total number of cases\n   */\n  total: number;\n\n  /**\n   * Number of passing cases\n   */\n  passed: number;\n\n  /**\n   * Number of failing cases\n   */\n  failed: number;\n\n  /**\n   * Individual case results\n   */\n  caseResults: Array<EvalCaseResult>;\n\n  /**\n   * Overall execution time in milliseconds\n   */\n  durationMs: number;\n}\n\n/**\n * Options for running eval dataset\n */\nexport interface EvalRunnerOptions {\n  /**\n   * The dataset to run\n   */\n  dataset: EvalDataset;\n\n  /**\n   * Schema registry for schema validation by name\n   *\n   * Maps schema names to Zod schemas for use with expect.schema\n   *\n   * @example\n   * ```typescript\n   * {\n   *   schemas: {\n   *     WeatherResponse: z.object({ temperature: z.number() }),\n   *     ErrorResponse: z.object({ error: z.string() }),\n   *   }\n   * }\n   * ```\n   */\n  schemas?: Record<string, ZodType>;\n\n  /**\n   * Judge configuration registry by ID\n   *\n   * Maps config IDs to JudgeConfig for use with expect.passesJudge.configId\n   */\n  judgeConfigs?: Record<string, JudgeConfig>;\n\n  /**\n   * Whether to stop on first failure\n   * @default false\n   */\n  stopOnFailure?: boolean;\n\n  /**\n   * Optional callback called after each case\n   */\n  onCaseComplete?: (result: EvalCaseResult) => void | Promise<void>;\n}\n\n/**\n * Options for running a single eval case\n */\nexport interface EvalCaseOptions {\n  /**\n   * Dataset name for the result (defaults to 'single-case')\n   */\n  datasetName?: string;\n\n  /**\n   * Schema registry for schema validation by name\n   */\n  schemas?: Record<string, ZodType>;\n\n  /**\n   * Judge configuration registry by ID\n   */\n  judgeConfigs?: Record<string, JudgeConfig>;\n}\n\nasync function executeToolCall(\n  evalCase: EvalCase,\n  mcp: MCPFixtureApi\n): Promise<{ response: unknown; error?: string }> {\n  const mode = evalCase.mode || 'direct';\n\n  try {\n    if (mode === 'llm_host') {\n      // LLM host simulation mode\n      if (!evalCase.scenario) {\n        throw new Error(\n          `Eval case ${evalCase.id}: scenario is required for llm_host mode`\n        );\n      }\n\n      if (!evalCase.llmHostConfig) {\n        throw new Error(\n          `Eval case ${evalCase.id}: llmHostConfig is required for llm_host mode`\n        );\n      }\n\n      const simulationResult = await simulateLLMHost(\n        mcp,\n        evalCase.scenario,\n        evalCase.llmHostConfig\n      );\n\n      if (!simulationResult.success) {\n        throw new Error(simulationResult.error || 'LLM host simulation failed');\n      }\n\n      return { response: simulationResult };\n    } else {\n      // Direct mode - call tool directly\n      if (!evalCase.toolName) {\n        throw new Error(\n          `Eval case ${evalCase.id}: toolName is required for direct mode`\n        );\n      }\n      if (!evalCase.args) {\n        throw new Error(\n          `Eval case ${evalCase.id}: args is required for direct mode`\n        );\n      }\n\n      const result = await mcp.callTool(evalCase.toolName, evalCase.args);\n\n      // For error expectations, return the full result so isError can be checked\n      // For other expectations, return the content (backwards compatible)\n      if (evalCase.expect?.isError !== undefined) {\n        return { response: result };\n      }\n      return { response: result.structuredContent ?? result.content };\n    }\n  } catch (err) {\n    return {\n      response: undefined,\n      error: err instanceof Error ? err.message : String(err),\n    };\n  }\n}\n\n/**\n * Determines if a case passed based on error and expectation results\n */\nfunction didCasePass(\n  error: string | undefined,\n  expectations: EvalCaseResult['expectations']\n): boolean {\n  return (\n    !error &&\n    Object.values(expectations).every(\n      (result) => result === undefined || result.pass\n    )\n  );\n}\n\n/**\n * Configuration for processing expect blocks\n */\ninterface ExpectBlockConfig {\n  schemas?: Record<string, ZodType>;\n  judgeConfigs?: Record<string, JudgeConfig>;\n  playwrightExpect?: Expect;\n}\n\n/**\n * Processes the new unified expect block using validators\n *\n * This function translates the expect block into validation results,\n * calling the appropriate validators for each field.\n */\nasync function runExpectBlockValidations(\n  expectBlock: EvalExpectBlock,\n  response: unknown,\n  config: ExpectBlockConfig\n): Promise<EvalCaseResult['expectations']> {\n  const results: EvalCaseResult['expectations'] = {};\n\n  // response (toMatchToolResponse)\n  if (expectBlock.response !== undefined) {\n    const validation = validateResponse(response, expectBlock.response);\n    results.exact = {\n      pass: validation.pass,\n      details: validation.message,\n    };\n  }\n\n  // schema (toMatchToolSchema)\n  if (expectBlock.schema !== undefined) {\n    const schema = config.schemas?.[expectBlock.schema];\n    if (!schema) {\n      results.schema = {\n        pass: false,\n        details: `Schema \"${expectBlock.schema}\" not found in schemas registry`,\n      };\n    } else {\n      const validation = validateSchema(response, schema);\n      results.schema = {\n        pass: validation.pass,\n        details: validation.message,\n      };\n    }\n  }\n\n  // containsText (toContainToolText)\n  if (expectBlock.containsText !== undefined) {\n    const validation = validateText(response, expectBlock.containsText);\n    results.textContains = {\n      pass: validation.pass,\n      details: validation.message,\n    };\n  }\n\n  // matchesPattern (toMatchToolPattern)\n  if (expectBlock.matchesPattern !== undefined) {\n    const validation = validatePattern(response, expectBlock.matchesPattern);\n    results.regex = {\n      pass: validation.pass,\n      details: validation.message,\n    };\n  }\n\n  // isError (toBeToolError)\n  if (expectBlock.isError !== undefined) {\n    const validation = validateError(response, expectBlock.isError);\n    results.error = {\n      pass: validation.pass,\n      details: validation.message,\n    };\n  }\n\n  // responseSize (toHaveToolResponseSize)\n  if (expectBlock.responseSize !== undefined) {\n    const validation = validateSize(response, expectBlock.responseSize);\n    results.size = {\n      pass: validation.pass,\n      details: validation.message,\n    };\n  }\n\n  // passesJudge (toPassToolJudge)\n  if (expectBlock.passesJudge !== undefined) {\n    const {\n      rubric,\n      reference,\n      threshold = 0.7,\n      configId,\n    } = expectBlock.passesJudge;\n\n    // Get judge config\n    const judgeConfig = configId ? (config.judgeConfigs?.[configId] ?? {}) : {};\n\n    try {\n      const judge = createJudge(judgeConfig);\n      const judgeResult = await judge.evaluate(\n        response,\n        reference ?? null,\n        rubric\n      );\n      const score = judgeResult.score ?? (judgeResult.pass ? 1.0 : 0.0);\n      const passed = score >= threshold;\n\n      results.judge = {\n        pass: passed,\n        details: passed\n          ? `Judge passed with score ${score.toFixed(2)}`\n          : `Judge failed with score ${score.toFixed(2)} (threshold: ${threshold}). ${judgeResult.reasoning ?? ''}`,\n      };\n    } catch (err) {\n      results.judge = {\n        pass: false,\n        details: `Judge evaluation error: ${err instanceof Error ? err.message : String(err)}`,\n      };\n    }\n  }\n\n  // snapshot (toMatchToolSnapshot) - requires Playwright expect\n  if (expectBlock.snapshot !== undefined) {\n    if (!config.playwrightExpect) {\n      results.snapshot = {\n        pass: false,\n        details: 'Snapshot testing requires expect in context',\n      };\n    } else {\n      try {\n        // eslint-disable-next-line @typescript-eslint/await-thenable\n        await config\n          .playwrightExpect(response)\n          .toMatchSnapshot(expectBlock.snapshot);\n        results.snapshot = {\n          pass: true,\n          details: `Matches snapshot \"${expectBlock.snapshot}\"`,\n        };\n      } catch (err) {\n        results.snapshot = {\n          pass: false,\n          details: err instanceof Error ? err.message : String(err),\n        };\n      }\n    }\n  }\n\n  return results;\n}\n\n/**\n * Runs a single eval case and returns the result\n *\n * @param evalCase - The eval case to run\n * @param context - Context containing mcp, testInfo, expect\n * @param options - Optional configuration (datasetName, schemas, judgeConfigs)\n * @returns The result of running the eval case\n *\n * @example\n * ```typescript\n * const result = await runEvalCase(\n *   evalCase,\n *   { mcp, testInfo, expect },\n *   { schemas: { WeatherResponse: WeatherSchema } }\n * );\n *\n * expect(result.pass).toBe(true);\n * ```\n */\nexport async function runEvalCase(\n  evalCase: EvalCase,\n  context: EvalContext,\n  options: EvalCaseOptions = {}\n): Promise<EvalCaseResult> {\n  const startTime = Date.now();\n  const mode = evalCase.mode || 'direct';\n\n  // Execute tool call\n  const { response, error } = await executeToolCall(evalCase, context.mcp);\n\n  // Collect expectation results from expect block\n  let expectationResults: EvalCaseResult['expectations'] = {};\n\n  if (!error && evalCase.expect) {\n    expectationResults = await runExpectBlockValidations(\n      evalCase.expect,\n      response,\n      {\n        schemas: options.schemas,\n        judgeConfigs: options.judgeConfigs,\n        playwrightExpect: context.expect,\n      }\n    );\n  }\n\n  // Build result - use test context for authType and project (Playwright is source of truth)\n  return {\n    id: evalCase.id,\n    datasetName: options.datasetName ?? 'single-case',\n    toolName: evalCase.toolName ?? evalCase.scenario ?? 'unknown',\n    mode,\n    source: 'eval',\n    pass: didCasePass(error, expectationResults),\n    response,\n    error,\n    expectations: expectationResults,\n    authType: context.mcp.authType,\n    project: context.mcp.project,\n    durationMs: Date.now() - startTime,\n  };\n}\n\n/**\n * Runs an eval dataset against an MCP server\n *\n * This function composes runEvalCase() for each case in the dataset,\n * adding dataset-level features like stopOnFailure and callbacks.\n *\n * @param options - Eval runner options (dataset, schemas, judgeConfigs)\n * @param context - Eval context (mcp fixture, optional testInfo, optional expect)\n * @returns Eval results\n *\n * @example\n * // Basic usage\n * const result = await runEvalDataset(\n *   {\n *     dataset,\n *     schemas: { WeatherResponse: WeatherSchema },\n *   },\n *   { mcp }\n * );\n *\n * @example\n * // With MCP reporter integration\n * test('eval dataset', async ({ mcp }, testInfo) => {\n *   const result = await runEvalDataset(\n *     { dataset },\n *     { mcp, testInfo }  // testInfo enables MCP reporter\n *   );\n * });\n */\nexport async function runEvalDataset(\n  options: EvalRunnerOptions,\n  context: EvalContext\n): Promise<EvalRunnerResult> {\n  const {\n    dataset,\n    schemas,\n    judgeConfigs,\n    stopOnFailure = false,\n    onCaseComplete,\n  } = options;\n\n  const startTime = Date.now();\n  const caseResults: EvalCaseResult[] = [];\n\n  // Context is used as-is (judge is handled via judgeConfigs in expect block)\n  const enrichedContext = context;\n\n  // Merge schemas from dataset and options\n  const allSchemas = {\n    ...dataset.schemas,\n    ...schemas,\n  };\n\n  // Run each case\n  for (const evalCase of dataset.cases) {\n    const result = await runEvalCase(evalCase, enrichedContext, {\n      datasetName: dataset.name,\n      schemas: allSchemas,\n      judgeConfigs,\n    });\n\n    caseResults.push(result);\n\n    // Call onCaseComplete callback\n    if (onCaseComplete) {\n      await onCaseComplete(result);\n    }\n\n    // Stop on failure if requested\n    if (stopOnFailure && !result.pass) {\n      break;\n    }\n  }\n\n  const total = caseResults.length;\n  const passed = caseResults.filter((r) => r.pass).length;\n\n  const result: EvalRunnerResult = {\n    total,\n    passed,\n    failed: total - passed,\n    caseResults,\n    durationMs: Date.now() - startTime,\n  };\n\n  // Attach results for MCP reporter if testInfo is provided\n  if (context.testInfo) {\n    await context.testInfo.attach('mcp-test-results', {\n      contentType: 'application/json',\n      body: Buffer.from(JSON.stringify({ caseResults })),\n    });\n  }\n\n  return result;\n}\n","/**\n * Tool call validator for LLM host mode\n *\n * Validates that the LLM made the expected tool calls with correct arguments\n */\n\nimport type { EvalExpectationResult } from '../../types/index.js';\nimport type { EvalCase } from '../datasetTypes.js';\nimport type { ExpectedToolCall, LLMToolCall } from './llmHostTypes.js';\n\n/**\n * Tool call validation function signature\n */\nexport type ToolCallValidator = (\n  evalCase: EvalCase,\n  response: unknown\n) => Promise<EvalExpectationResult>;\n\n/**\n * Checks if two argument objects match (partial match)\n *\n * @param actual - Actual arguments from LLM\n * @param expected - Expected arguments (can be partial)\n * @returns true if all expected keys match actual values\n */\nfunction argumentsMatch(\n  actual: Record<string, unknown>,\n  expected: Record<string, unknown>\n): boolean {\n  for (const key of Object.keys(expected)) {\n    if (!(key in actual)) {\n      return false;\n    }\n\n    const actualValue = actual[key];\n    const expectedValue = expected[key];\n\n    // Deep equality check\n    if (JSON.stringify(actualValue) !== JSON.stringify(expectedValue)) {\n      return false;\n    }\n  }\n\n  return true;\n}\n\n/**\n * Finds matching tool call in actual calls\n *\n * @param expected - Expected tool call\n * @param actualCalls - Actual tool calls made by LLM\n * @returns Matching tool call or null\n */\nfunction findMatchingCall(\n  expected: ExpectedToolCall,\n  actualCalls: Array<LLMToolCall>\n): LLMToolCall | null {\n  for (const actualCall of actualCalls) {\n    if (actualCall.name !== expected.name) {\n      continue;\n    }\n\n    if (!expected.arguments) {\n      // Name match is sufficient\n      return actualCall;\n    }\n\n    if (argumentsMatch(actualCall.arguments, expected.arguments)) {\n      return actualCall;\n    }\n  }\n\n  return null;\n}\n\n/**\n * Creates a tool call validator for LLM host mode\n *\n * Validates that the LLM made the expected tool calls with correct arguments.\n * Supports partial argument matching and optional calls.\n *\n * @returns Validator function\n *\n * @example\n * ```typescript\n * // In your eval case:\n * {\n *   \"id\": \"weather-london\",\n *   \"mode\": \"llm_host\",\n *   \"scenario\": \"Get the weather for London\",\n *   \"expectedToolCalls\": [\n *     {\n *       \"name\": \"get_weather\",\n *       \"arguments\": { \"city\": \"London\" },\n *       \"required\": true\n *     }\n *   ]\n * }\n * ```\n */\nexport function createToolCallValidator(): ToolCallValidator {\n  return async (evalCase: EvalCase, response: unknown) => {\n    // Extract expected tool calls from eval case metadata\n    const expectedCalls = evalCase.metadata?.expectedToolCalls as\n      | Array<ExpectedToolCall>\n      | undefined;\n\n    if (!expectedCalls || expectedCalls.length === 0) {\n      return {\n        pass: true,\n        details: 'No expected tool calls specified',\n      };\n    }\n\n    // Extract actual tool calls from response\n    const responseObj = response as { toolCalls?: Array<LLMToolCall> } | null;\n    const actualCalls = responseObj?.toolCalls;\n\n    if (!actualCalls || actualCalls.length === 0) {\n      const requiredCalls = expectedCalls.filter(\n        (call) => call.required !== false\n      );\n      if (requiredCalls.length > 0) {\n        return {\n          pass: false,\n          details: `Expected ${requiredCalls.length} tool call(s), but LLM made no tool calls`,\n        };\n      }\n      return {\n        pass: true,\n        details: 'No tool calls expected or made',\n      };\n    }\n\n    // Validate each expected call\n    const missingCalls: Array<ExpectedToolCall> = [];\n    const foundCalls: Array<{\n      expected: ExpectedToolCall;\n      actual: LLMToolCall;\n    }> = [];\n\n    for (const expectedCall of expectedCalls) {\n      const matchingCall = findMatchingCall(expectedCall, actualCalls);\n\n      if (!matchingCall) {\n        if (expectedCall.required !== false) {\n          missingCalls.push(expectedCall);\n        }\n      } else {\n        foundCalls.push({\n          expected: expectedCall,\n          actual: matchingCall,\n        });\n      }\n    }\n\n    if (missingCalls.length > 0) {\n      const missingDetails = missingCalls\n        .map((call) => `${call.name}(${JSON.stringify(call.arguments || {})})`)\n        .join(', ');\n\n      return {\n        pass: false,\n        details: `Missing required tool call(s): ${missingDetails}. Actual calls: ${actualCalls.map((c) => c.name).join(', ')}`,\n      };\n    }\n\n    return {\n      pass: true,\n      details: `All ${expectedCalls.length} expected tool call(s) were made correctly`,\n    };\n  };\n}\n","import type { MCPFixtureApi } from '../mcp/fixtures/mcpFixture.js';\nimport type { TestInfo } from '@playwright/test';\nimport type {\n  Tool,\n  Resource,\n  Prompt,\n  ServerCapabilities,\n  Implementation,\n} from '@modelcontextprotocol/sdk/types.js';\n\n/**\n * Options for conformance checks\n */\nexport interface MCPConformanceOptions {\n  /**\n   * List of tools that must be present\n   */\n  requiredTools?: Array<string>;\n\n  /**\n   * Whether to validate tool schemas\n   * @default true\n   */\n  validateSchemas?: boolean;\n\n  /**\n   * Whether to check server info is present\n   * @default true\n   */\n  checkServerInfo?: boolean;\n\n  /**\n   * Whether to check resources capability (if declared by server)\n   * @default true\n   */\n  checkResources?: boolean;\n\n  /**\n   * Whether to check prompts capability (if declared by server)\n   * @default true\n   */\n  checkPrompts?: boolean;\n}\n\n/**\n * Individual check result\n */\nexport interface MCPConformanceCheck {\n  name: string;\n  pass: boolean;\n  message: string;\n}\n\n/**\n * Raw MCP responses for snapshotting\n */\nexport interface MCPConformanceRaw {\n  /**\n   * Server info (name, version)\n   * null if not available\n   */\n  serverInfo: Implementation | null;\n\n  /**\n   * Server capabilities\n   * null if not available\n   */\n  capabilities: ServerCapabilities | null;\n\n  /**\n   * List of tools from the server\n   */\n  tools: Tool[];\n\n  /**\n   * List of resources from the server\n   * null if server doesn't declare resources capability\n   */\n  resources: Resource[] | null;\n\n  /**\n   * List of prompts from the server\n   * null if server doesn't declare prompts capability\n   */\n  prompts: Prompt[] | null;\n}\n\n/**\n * Result of conformance checks\n */\nexport interface MCPConformanceResult {\n  /**\n   * Whether all checks passed\n   */\n  pass: boolean;\n\n  /**\n   * List of check results\n   */\n  checks: MCPConformanceCheck[];\n\n  /**\n   * Raw MCP responses for snapshotting\n   *\n   * @example\n   * ```typescript\n   * const result = await runConformanceChecks(mcp);\n   * expect(result.raw.tools).toMatchSnapshot();\n   * expect(result.raw.capabilities).toMatchSnapshot();\n   * ```\n   */\n  raw: MCPConformanceRaw;\n}\n\n/**\n * Runs MCP protocol conformance checks\n *\n * Validates that the MCP server conforms to expected protocol behavior.\n * Returns both assertion results and raw MCP responses for snapshotting.\n *\n * When testInfo is provided, results are automatically attached for the MCP reporter.\n *\n * @param mcp - MCP fixture API\n * @param options - Conformance check options\n * @param testInfo - Optional Playwright TestInfo for reporter integration\n * @returns Conformance check results with raw responses\n *\n * @example\n * ```typescript\n * // Basic usage\n * const result = await runConformanceChecks(mcp, {\n *   requiredTools: ['get_weather', 'search_docs'],\n *   validateSchemas: true,\n * });\n *\n * // Check assertions\n * expect(result.pass).toBe(true);\n *\n * // With reporter integration (recommended in Playwright tests)\n * const result = await runConformanceChecks(mcp, {\n *   requiredTools: ['search'],\n * }, testInfo);\n *\n * // Snapshot raw responses\n * expect(result.raw.tools).toMatchSnapshot();\n * expect(result.raw.capabilities).toMatchSnapshot();\n * ```\n */\nexport async function runConformanceChecks(\n  mcp: MCPFixtureApi,\n  options: MCPConformanceOptions = {},\n  testInfo?: TestInfo\n): Promise<MCPConformanceResult> {\n  const {\n    requiredTools = [],\n    validateSchemas = true,\n    checkServerInfo = true,\n    checkResources = true,\n    checkPrompts = true,\n  } = options;\n\n  const checks: MCPConformanceCheck[] = [];\n  const raw: MCPConformanceRaw = {\n    serverInfo: null,\n    capabilities: null,\n    tools: [],\n    resources: null,\n    prompts: null,\n  };\n\n  // Get server info\n  const serverInfo = mcp.getServerInfo();\n  if (serverInfo) {\n    raw.serverInfo = serverInfo as Implementation;\n  }\n\n  // Check 1: Server info is present\n  if (checkServerInfo) {\n    checks.push({\n      name: 'server_info_present',\n      pass: serverInfo !== null,\n      message: serverInfo\n        ? `Server info: ${serverInfo.name ?? 'unknown'} v${serverInfo.version ?? 'unknown'}`\n        : 'Server info is missing',\n    });\n  }\n\n  // Get capabilities from client\n  const capabilities = mcp.client.getServerCapabilities();\n  if (capabilities) {\n    raw.capabilities = capabilities;\n  }\n\n  // Check 2: Capabilities are valid\n  checks.push({\n    name: 'capabilities_valid',\n    pass: capabilities !== undefined,\n    message: capabilities\n      ? `Server capabilities: ${formatCapabilities(capabilities)}`\n      : 'Server capabilities not available',\n  });\n\n  // Check 3: List tools returns valid response\n  let tools: Tool[] = [];\n  try {\n    tools = await mcp.listTools();\n    raw.tools = tools;\n    checks.push({\n      name: 'list_tools_succeeds',\n      pass: true,\n      message: `listTools returned ${tools.length} tools`,\n    });\n  } catch (error) {\n    checks.push({\n      name: 'list_tools_succeeds',\n      pass: false,\n      message: `listTools failed: ${error instanceof Error ? error.message : String(error)}`,\n    });\n    const pass = checks.every((check) => check.pass);\n    return { pass, checks, raw };\n  }\n\n  // Check 4: Required tools are present\n  if (requiredTools.length > 0) {\n    const toolNames = new Set(tools.map((t) => t.name));\n    const missingTools = requiredTools.filter((name) => !toolNames.has(name));\n\n    checks.push({\n      name: 'required_tools_present',\n      pass: missingTools.length === 0,\n      message:\n        missingTools.length === 0\n          ? `All ${requiredTools.length} required tools are present`\n          : `Missing required tools: ${missingTools.join(', ')}`,\n    });\n  }\n\n  // Check 5: Tool schemas are valid\n  if (validateSchemas && tools.length > 0) {\n    const invalidTools: Array<string> = [];\n\n    for (const tool of tools) {\n      // Check that tool has required fields\n      if (!tool.name) {\n        invalidTools.push(`(unnamed tool): missing name`);\n        continue;\n      }\n\n      if (!tool.inputSchema) {\n        invalidTools.push(`${tool.name}: missing inputSchema`);\n        continue;\n      }\n\n      // Check that inputSchema is an object schema\n      if (tool.inputSchema.type !== 'object') {\n        invalidTools.push(\n          `${tool.name}: inputSchema.type must be \"object\", got \"${String(tool.inputSchema.type)}\"`\n        );\n      }\n    }\n\n    checks.push({\n      name: 'tool_schemas_valid',\n      pass: invalidTools.length === 0,\n      message:\n        invalidTools.length === 0\n          ? `All ${tools.length} tools have valid schemas`\n          : `Invalid tool schemas:\\n  ${invalidTools.join('\\n  ')}`,\n    });\n  }\n\n  // Check 6: List resources (only if server declares resources capability)\n  if (checkResources && capabilities?.resources) {\n    try {\n      const resourcesResult = await mcp.client.listResources();\n      raw.resources = resourcesResult.resources;\n      checks.push({\n        name: 'list_resources_succeeds',\n        pass: true,\n        message: `listResources returned ${resourcesResult.resources.length} resources`,\n      });\n    } catch (error) {\n      checks.push({\n        name: 'list_resources_succeeds',\n        pass: false,\n        message: `listResources failed: ${error instanceof Error ? error.message : String(error)}`,\n      });\n    }\n  }\n\n  // Check 7: List prompts (only if server declares prompts capability)\n  if (checkPrompts && capabilities?.prompts) {\n    try {\n      const promptsResult = await mcp.client.listPrompts();\n      raw.prompts = promptsResult.prompts;\n      checks.push({\n        name: 'list_prompts_succeeds',\n        pass: true,\n        message: `listPrompts returned ${promptsResult.prompts.length} prompts`,\n      });\n    } catch (error) {\n      checks.push({\n        name: 'list_prompts_succeeds',\n        pass: false,\n        message: `listPrompts failed: ${error instanceof Error ? error.message : String(error)}`,\n      });\n    }\n  }\n\n  // Check 8: Calling invalid tool returns error\n  try {\n    const result = await mcp.callTool('__nonexistent_tool__', {});\n    // MCP SDK may return isError: true instead of throwing\n    const hasError = result.isError === true;\n    checks.push({\n      name: 'invalid_tool_returns_error',\n      pass: hasError,\n      message: hasError\n        ? 'Nonexistent tool correctly returned an error'\n        : 'Calling nonexistent tool should have returned an error',\n    });\n  } catch {\n    // Or it may throw - both are acceptable\n    checks.push({\n      name: 'invalid_tool_returns_error',\n      pass: true,\n      message: 'Nonexistent tool correctly threw an error',\n    });\n  }\n\n  const pass = checks.every((check) => check.pass);\n\n  const result: MCPConformanceResult = { pass, checks, raw };\n\n  // Attach results for MCP reporter if testInfo is provided\n  if (testInfo) {\n    await testInfo.attach('mcp-conformance-checks', {\n      contentType: 'application/json',\n      body: JSON.stringify(\n        {\n          operation: 'conformanceChecks',\n          pass,\n          checks,\n          serverInfo: raw.serverInfo,\n          capabilities: raw.capabilities,\n          toolCount: raw.tools.length,\n          authType: mcp.authType,\n          project: mcp.project,\n        },\n        null,\n        2\n      ),\n    });\n  }\n\n  return result;\n}\n\n/**\n * Formats server capabilities for display\n */\nfunction formatCapabilities(capabilities: ServerCapabilities): string {\n  const parts: string[] = [];\n  if (capabilities.tools) parts.push('tools');\n  if (capabilities.resources) parts.push('resources');\n  if (capabilities.prompts) parts.push('prompts');\n  if (capabilities.logging) parts.push('logging');\n  if (capabilities.completions) parts.push('completions');\n  if (capabilities.experimental) parts.push('experimental');\n  return parts.length > 0 ? parts.join(', ') : 'none declared';\n}\n"]}