@gleanwork/mcp-server-tester 1.0.0-beta.8 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/mcp/response.ts","../../src/assertions/validators/utils.ts","../../src/assertions/validators/response.ts","../../src/assertions/matchers/toMatchToolResponse.ts","../../src/assertions/validators/schema.ts","../../src/assertions/matchers/toMatchToolSchema.ts","../../src/assertions/validators/text.ts","../../src/assertions/matchers/toContainToolText.ts","../../src/assertions/validators/pattern.ts","../../src/assertions/matchers/toMatchToolPattern.ts","../../src/assertions/matchers/toMatchToolSnapshot.ts","../../src/assertions/validators/error.ts","../../src/assertions/matchers/toBeToolError.ts","../../src/judge/rubrics.ts","../../src/judge/judgeTypes.ts","../../src/judge/anthropicJudge.ts","../../src/judge/vertexAnthropicJudge.ts","../../src/judge/claudeAgentJudge.ts","../../src/judge/openaiJudge.ts","../../src/judge/googleJudge.ts","../../src/judge/judgeClient.ts","../../src/judge/judgeRegistry.ts","../../src/assertions/validators/judge.ts","../../src/assertions/matchers/toPassToolJudge.ts","../../src/assertions/validators/size.ts","../../src/assertions/matchers/toHaveToolResponseSize.ts","../../src/assertions/matchers/toSatisfyToolPredicate.ts","../../src/assertions/validators/toolCalls.ts","../../src/assertions/matchers/toHaveToolCalls.ts","../../src/assertions/matchers/toHaveToolCallCount.ts","../../src/assertions/matchers/index.ts","../../src/config/mcpConfig.ts","../../src/debug.ts","../../package.json","../../src/auth/oauthFlow.ts","../../src/mcp/clientFactory.ts","../../src/mcp/fixtures/mcpFixture.ts","../../src/auth/oauthClientProvider.ts","../../src/auth/discovery.ts","../../src/auth/storage.ts","../../src/auth/cli.ts","../../src/fixtures/mcp.ts"],"names":["extractText","path","truncateForDisplay","baseExpect","buildJudgePrompt","parseJudgeResponse","z","createDebug","UndiciAgent","fs","oauth2","debug","base"],"mappings":"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","file":"mcp.js","sourcesContent":["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 content as a direct string (single content block format)\n if (typeof r.content === 'string') {\n return 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 // Per MCP spec, content is required in CallToolResult — isError alone is insufficient\n return Array.isArray(v.content);\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/**\n * Normalizes whitespace in text for consistent comparison\n *\n * Collapses multiple whitespace characters (spaces, tabs, newlines) into single spaces\n * and trims leading/trailing whitespace.\n *\n * @param text - Text to normalize\n * @returns Normalized text with collapsed whitespace\n *\n * @example\n * ```typescript\n * normalizeWhitespace(' hello\\n\\n world ');\n * // Returns: \"hello world\"\n * ```\n */\nexport function normalizeWhitespace(text: string): string {\n return text.replace(/\\s+/g, ' ').trim();\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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 let pattern: RegExp;\n if (sanitizer.pattern instanceof RegExp) {\n pattern = sanitizer.pattern;\n } else {\n try {\n pattern = new RegExp(sanitizer.pattern, 'g');\n } catch {\n throw new Error(\n `toMatchToolSnapshot: invalid regex pattern \"${sanitizer.pattern}\" in sanitizer`\n );\n }\n }\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 * @remarks\n * **Requires Playwright test context.** This matcher calls `expect(content).toMatchSnapshot()`\n * internally, which only works inside a Playwright test (i.e., when `testInfo` is available).\n * Calling it outside a Playwright test will throw a cryptic context error.\n *\n * To test sanitizer logic without a Playwright context, use the exported `applySanitizers`\n * function directly.\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 * 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 * 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","/**\n * Built-in judge rubrics matching Glean EvalV2's named judge types.\n * Use these for consistent, standardized evaluations across teams.\n *\n * All built-in rubrics use a 5-point scale: 0.0 / 0.25 / 0.5 / 0.75 / 1.0\n */\nexport type BuiltInRubric =\n | 'correctness'\n | 'completeness'\n | 'groundedness'\n | 'instruction-following'\n | 'conciseness';\n\nexport const BUILT_IN_RUBRICS: Record<BuiltInRubric, string> = {\n correctness:\n 'Evaluate whether the response is factually correct and accurately answers the question. ' +\n 'Compare against the reference answer if provided. ' +\n 'Score 1.0 for fully correct with no errors; ' +\n 'Score 0.75 for mostly correct with one minor inaccuracy or omission; ' +\n 'Score 0.5 for partially correct — answers part of the question but misses key elements; ' +\n 'Score 0.25 for minimally relevant but substantially incorrect or missing most key details; ' +\n 'Score 0.0 for incorrect, irrelevant, or directly contradicting the reference.',\n\n completeness:\n 'Evaluate whether the response fully addresses all aspects of the question. ' +\n 'Score 1.0 if the response covers all key points comprehensively; ' +\n 'Score 0.75 if the response covers most key points with one minor gap; ' +\n 'Score 0.5 if the response partially answers — covers some aspects but misses others; ' +\n 'Score 0.25 if the response touches on the topic but misses most key aspects; ' +\n 'Score 0.0 if major aspects of the question are entirely missing or the response is off-topic.',\n\n groundedness:\n 'Evaluate whether all claims in the response are supported by the retrieved context or reference. ' +\n 'Penalize unsupported assertions or hallucinated facts. ' +\n 'Score 1.0 for fully grounded — every claim is traceable to the provided context; ' +\n 'Score 0.75 for mostly grounded with one minor unsupported detail; ' +\n 'Score 0.5 for partially grounded — some claims are supported but notable hallucinations are present; ' +\n 'Score 0.25 for minimally grounded — most claims are unsupported or invented; ' +\n 'Score 0.0 for completely hallucinated or contradicting the provided context.',\n\n 'instruction-following':\n 'Evaluate whether the response follows the instructions given in the question. ' +\n 'Check format, tone, constraints, and task completion. ' +\n 'Score 1.0 for full compliance — all instructions are followed precisely; ' +\n 'Score 0.75 for mostly compliant with one minor deviation from the instructions; ' +\n 'Score 0.5 for partial compliance — some instructions followed but key constraints violated; ' +\n 'Score 0.25 for minimal compliance — the response loosely addresses the task but ignores most instructions; ' +\n 'Score 0.0 for non-compliance — the response disregards the instructions entirely.',\n\n conciseness:\n 'Evaluate whether the response is appropriately concise without losing important information. ' +\n 'Penalize unnecessary verbosity, padding, or repetition. ' +\n 'Score 1.0 for well-sized — concise and complete with no unnecessary content; ' +\n 'Score 0.75 for slightly verbose but no information is lost or repeated; ' +\n 'Score 0.5 for moderately verbose — some padding or repetition that reduces clarity; ' +\n 'Score 0.25 for excessively verbose — significantly overlong with substantial filler or repetition; ' +\n 'Score 0.0 for extremely verbose — so padded or repetitive that the core answer is obscured.',\n};\n\n/** A rubric specification: either a built-in named rubric or custom text. */\nexport type RubricSpec = BuiltInRubric | { text: string };\n\n/**\n * Returns true if `s` is a built-in rubric name.\n */\nexport function isBuiltInRubric(s: unknown): s is BuiltInRubric {\n return typeof s === 'string' && s in BUILT_IN_RUBRICS;\n}\n\n/**\n * Resolves a RubricSpec to its full rubric text.\n * - Built-in name → returns the expanded rubric text from BUILT_IN_RUBRICS\n * - Custom object → returns rubric.text as-is\n */\nexport function resolveRubric(rubric: RubricSpec): string {\n if (typeof rubric === 'string') {\n return BUILT_IN_RUBRICS[rubric];\n }\n return rubric.text;\n}\n","import { z } from 'zod';\n\n/**\n * Zod schema for validating judge LLM responses.\n * Ensures the response has the required structure before it is used.\n */\nexport const JudgeResponseSchema = z.object({\n pass: z.boolean(),\n score: z.number().min(0).max(1),\n reasoning: z.string(),\n});\n\n/**\n * The validated shape returned by a judge LLM.\n */\nexport type JudgeResponse = z.infer<typeof JudgeResponseSchema>;\n\n/**\n * Usage metrics from Claude Agent SDK response\n */\nexport interface UsageMetrics {\n /**\n * Number of input tokens consumed\n */\n inputTokens: number;\n\n /**\n * Number of output tokens generated\n */\n outputTokens: number;\n\n /**\n * Total cost in USD\n */\n totalCostUsd: number;\n\n /**\n * Execution duration in milliseconds\n */\n durationMs: number;\n\n /**\n * API call duration in milliseconds (excluding network overhead)\n */\n durationApiMs?: number;\n\n /**\n * Number of tokens read from cache\n */\n cacheReadInputTokens?: number;\n\n /**\n * Number of tokens written to cache\n */\n cacheCreationInputTokens?: number;\n}\n\n/** Valid LLM judge provider kinds. */\nexport type ProviderKind =\n | 'anthropic'\n | 'vertex-anthropic'\n | 'anthropic-agent-sdk'\n | 'openai'\n | 'google';\n\n/**\n * Configuration for an LLM judge\n */\nexport interface JudgeConfig {\n /**\n * LLM provider to use\n * @default 'anthropic'\n */\n provider?: ProviderKind;\n\n /**\n * Environment variable name containing the API key\n * @default 'ANTHROPIC_API_KEY'\n */\n apiKeyEnvVar?: string;\n\n /**\n * Model to use for judging\n * @default 'claude-sonnet-4-20250514'\n */\n model?: string;\n\n /**\n * Maximum tokens for response\n * @default 1000\n */\n maxTokens?: number;\n\n /**\n * Temperature (0-1, lower is more deterministic)\n * @default 0.0\n */\n temperature?: number;\n\n /**\n * Maximum budget in USD for the judge evaluation\n * @default 0.10\n */\n maxBudgetUsd?: number;\n\n /**\n * Maximum size (in bytes) for tool output before failing the test\n * When set, the judge will fail if the candidate response exceeds this size\n */\n maxToolOutputSize?: number;\n}\n\n/**\n * Result from LLM judge evaluation\n */\nexport interface JudgeResult {\n /**\n * Whether the evaluation passed\n */\n pass: boolean;\n\n /**\n * Numeric score (0-1, where 1 is best)\n */\n score?: number;\n\n /**\n * Reasoning/explanation from the judge\n */\n reasoning?: string;\n\n /**\n * Usage metrics from the Claude Agent SDK\n */\n usage?: UsageMetrics;\n\n /**\n * Size of the candidate response in bytes (for maxToolOutputSize tracking)\n */\n candidateSizeBytes?: number;\n\n /**\n * Whether the candidate exceeded maxToolOutputSize\n */\n exceedsMaxToolOutputSize?: boolean;\n\n /**\n * Standard deviation of individual rep scores.\n * Only populated when the judge was run with reps > 1.\n */\n scoreStdDev?: number;\n\n /**\n * True when the standard deviation across reps exceeds 0.2, indicating\n * that the rubric may be ambiguous or the judge is non-deterministic.\n * Only populated when the judge was run with reps > 1.\n */\n highVariance?: boolean;\n\n /**\n * Individual scores from each judge rep.\n * Only populated when the judge was run with reps > 1.\n */\n scores?: number[];\n}\n\nexport type { BuiltInRubric, RubricSpec } from './rubrics.js';\nexport { BUILT_IN_RUBRICS, resolveRubric, isBuiltInRubric } from './rubrics.js';\n\n/**\n * LLM judge client interface\n */\nexport interface Judge {\n /**\n * Evaluates a candidate response against a reference\n *\n * @param candidate - The actual response to evaluate\n * @param reference - The expected/reference response (or null if not applicable)\n * @param rubric - The evaluation rubric/criteria\n * @returns Evaluation result with usage metrics\n */\n evaluate(\n candidate: unknown,\n reference: unknown,\n rubric: string\n ): Promise<JudgeResult>;\n}\n","/* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any */\nimport type { Judge, JudgeConfig, JudgeResult } from './judgeTypes.js';\nimport { JudgeResponseSchema } from './judgeTypes.js';\n\n/**\n * Creates an Anthropic-backed LLM judge using the Anthropic SDK directly.\n * Requires the `@anthropic-ai/sdk` package and an Anthropic API key.\n */\nexport function createAnthropicJudge(config: JudgeConfig = {}): Judge {\n const apiKeyEnvVar = config.apiKeyEnvVar ?? 'ANTHROPIC_API_KEY';\n const apiKey = process.env[apiKeyEnvVar];\n if (!apiKey) {\n throw new Error(\n `Anthropic judge requires an API key. Set the ${apiKeyEnvVar} environment variable.`\n );\n }\n\n const model = config.model ?? 'claude-sonnet-4-20250514';\n const maxTokens = config.maxTokens ?? 1000;\n const temperature = config.temperature ?? 0.0;\n\n return {\n async evaluate(candidate, reference, rubric): Promise<JudgeResult> {\n let anthropicModule: any;\n try {\n // @ts-expect-error - optional: npm install @anthropic-ai/sdk\n anthropicModule = await import('@anthropic-ai/sdk');\n } catch (err) {\n throw new Error(\n 'Anthropic judge requires the `@anthropic-ai/sdk` package. ' +\n 'Install it with: npm install @anthropic-ai/sdk\\n' +\n `Original error: ${err instanceof Error ? err.message : String(err)}`\n );\n }\n\n const client = new anthropicModule.default({ apiKey });\n const prompt = buildJudgePrompt(candidate, reference, rubric);\n\n const startTime = Date.now();\n const response = await client.messages.create({\n model,\n max_tokens: maxTokens,\n temperature,\n system:\n 'You are an expert evaluator. Respond with valid JSON only: {\"pass\": true|false, \"score\": 0.0-1.0, \"reasoning\": \"explanation\"}',\n messages: [{ role: 'user', content: prompt }],\n });\n const durationMs = Date.now() - startTime;\n\n const textBlock = (response.content as any[]).find(\n (b: any) => b.type === 'text'\n );\n const text = (textBlock?.text as string) ?? '';\n const parsed = parseJudgeResponse(text);\n\n return {\n pass: parsed.pass,\n score: parsed.score,\n reasoning: parsed.reasoning,\n usage: {\n inputTokens: (response.usage?.input_tokens as number) ?? 0,\n outputTokens: (response.usage?.output_tokens as number) ?? 0,\n totalCostUsd: 0,\n durationMs,\n },\n };\n },\n };\n}\n\nfunction buildJudgePrompt(\n candidate: unknown,\n reference: unknown,\n rubric: string\n): string {\n const candidateStr =\n typeof candidate === 'string'\n ? candidate\n : JSON.stringify(candidate, null, 2);\n\n const referenceStr =\n reference !== null && reference !== undefined\n ? typeof reference === 'string'\n ? reference\n : JSON.stringify(reference, null, 2)\n : null;\n\n return (\n `Rubric:\\n${rubric}\\n\\n` +\n `<candidate_response>\\n${candidateStr}\\n</candidate_response>\\n\\n` +\n `<reference_answer>\\n${referenceStr ?? 'No reference provided.'}\\n</reference_answer>\\n\\n` +\n `Evaluate and return JSON: {\"pass\": boolean, \"score\": number (0-1), \"reasoning\": string}`\n );\n}\n\nfunction parseJudgeResponse(text: string): {\n pass: boolean;\n score: number;\n reasoning: string;\n} {\n const cleaned = text\n .replace(/```json\\n?/g, '')\n .replace(/```\\n?/g, '')\n .trim();\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(cleaned);\n } catch {\n throw new Error(`Failed to parse judge response as JSON: ${text}`);\n }\n\n const result = JudgeResponseSchema.safeParse(parsed);\n if (!result.success) {\n throw new Error(\n `Judge returned invalid response. Expected {pass, score, reasoning} but got: ${cleaned.slice(0, 500)}\\nValidation errors: ${JSON.stringify(result.error.issues)}`\n );\n }\n return result.data;\n}\n","/* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any */\nimport type { Judge, JudgeConfig, JudgeResult } from './judgeTypes.js';\nimport { JudgeResponseSchema } from './judgeTypes.js';\n\n/**\n * Creates an Anthropic-backed LLM judge that routes through Google Vertex AI.\n * Requires the `@anthropic-ai/vertex-sdk` package and Application Default Credentials.\n * Set GOOGLE_VERTEX_PROJECT and GOOGLE_VERTEX_LOCATION env vars.\n */\nexport function createVertexAnthropicJudge(config: JudgeConfig = {}): Judge {\n const model = config.model ?? 'claude-sonnet-4-20250514';\n const maxTokens = config.maxTokens ?? 1000;\n const temperature = config.temperature ?? 0.0;\n\n return {\n async evaluate(candidate, reference, rubric): Promise<JudgeResult> {\n let vertexModule: any;\n try {\n // @ts-expect-error - optional: npm install @anthropic-ai/vertex-sdk\n vertexModule = await import('@anthropic-ai/vertex-sdk');\n } catch (err) {\n throw new Error(\n 'Vertex Anthropic judge requires the `@anthropic-ai/vertex-sdk` package. ' +\n 'Install it with: npm install @anthropic-ai/vertex-sdk\\n' +\n `Original error: ${err instanceof Error ? err.message : String(err)}`\n );\n }\n\n const client = new vertexModule.AnthropicVertex({\n projectId:\n process.env.GOOGLE_VERTEX_PROJECT ?? process.env.CLOUD_ML_PROJECT_ID,\n region: process.env.GOOGLE_VERTEX_LOCATION ?? 'us-east5',\n });\n\n const prompt = buildJudgePrompt(candidate, reference, rubric);\n\n const startTime = Date.now();\n const response = await client.messages.create({\n model,\n max_tokens: maxTokens,\n temperature,\n system:\n 'You are an expert evaluator. Respond with valid JSON only: {\"pass\": true|false, \"score\": 0.0-1.0, \"reasoning\": \"explanation\"}',\n messages: [{ role: 'user', content: prompt }],\n });\n const durationMs = Date.now() - startTime;\n\n const textBlock = (response.content as any[]).find(\n (b: any) => b.type === 'text'\n );\n const text = (textBlock?.text as string) ?? '';\n const parsed = parseJudgeResponse(text);\n\n return {\n pass: parsed.pass,\n score: parsed.score,\n reasoning: parsed.reasoning,\n usage: {\n inputTokens: (response.usage?.input_tokens as number) ?? 0,\n outputTokens: (response.usage?.output_tokens as number) ?? 0,\n totalCostUsd: 0,\n durationMs,\n },\n };\n },\n };\n}\n\nfunction buildJudgePrompt(\n candidate: unknown,\n reference: unknown,\n rubric: string\n): string {\n const candidateStr =\n typeof candidate === 'string'\n ? candidate\n : JSON.stringify(candidate, null, 2);\n\n const referenceStr =\n reference !== null && reference !== undefined\n ? typeof reference === 'string'\n ? reference\n : JSON.stringify(reference, null, 2)\n : null;\n\n return (\n `Rubric:\\n${rubric}\\n\\n` +\n `<candidate_response>\\n${candidateStr}\\n</candidate_response>\\n\\n` +\n `<reference_answer>\\n${referenceStr ?? 'No reference provided.'}\\n</reference_answer>\\n\\n` +\n `Evaluate and return JSON: {\"pass\": boolean, \"score\": number (0-1), \"reasoning\": string}`\n );\n}\n\nfunction parseJudgeResponse(text: string): {\n pass: boolean;\n score: number;\n reasoning: string;\n} {\n const cleaned = text\n .replace(/```json\\n?/g, '')\n .replace(/```\\n?/g, '')\n .trim();\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(cleaned);\n } catch {\n throw new Error(`Failed to parse judge response as JSON: ${text}`);\n }\n\n const result = JudgeResponseSchema.safeParse(parsed);\n if (!result.success) {\n throw new Error(\n `Judge returned invalid response. Expected {pass, score, reasoning} but got: ${cleaned.slice(0, 500)}\\nValidation errors: ${JSON.stringify(result.error.issues)}`\n );\n }\n return result.data;\n}\n","import { query } from '@anthropic-ai/claude-agent-sdk';\nimport type {\n JudgeConfig,\n Judge,\n JudgeResult,\n UsageMetrics,\n} from './judgeTypes.js';\nimport { JudgeResponseSchema } 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,\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 candidateStr =\n typeof candidate === 'string'\n ? candidate\n : JSON.stringify(candidate, null, 2);\n\n const referenceStr =\n reference !== null && reference !== undefined\n ? typeof reference === 'string'\n ? reference\n : JSON.stringify(reference, null, 2)\n : null;\n\n const parts: Array<string> = [];\n\n parts.push('Rubric:\\n');\n parts.push(rubric);\n parts.push('\\n\\n<candidate_response>\\n');\n parts.push(candidateStr);\n parts.push('\\n</candidate_response>\\n\\n');\n\n parts.push('<reference_answer>\\n');\n parts.push(referenceStr ?? 'No reference provided.');\n parts.push('\\n</reference_answer>\\n\\n');\n\n parts.push(\n 'Evaluate the candidate response against the rubric' +\n (referenceStr !== null\n ? ', comparing it with the reference answer if helpful'\n : '') +\n '. Return JSON: {\"pass\": boolean, \"score\": number (0-1), \"reasoning\": string}'\n );\n\n return parts.join('');\n}\n\n/**\n * Parses and validates the JSON response from the judge, handling markdown code blocks.\n * Throws a descriptive error if the response cannot be parsed or fails schema validation.\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 let parsed: unknown;\n try {\n parsed = JSON.parse(jsonText);\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 parsed = JSON.parse(jsonMatch[0]);\n } else {\n throw new Error(`Failed to parse judge response as JSON: ${text}`);\n }\n }\n\n const result = JudgeResponseSchema.safeParse(parsed);\n if (!result.success) {\n throw new Error(\n `Judge returned invalid response. Expected {pass, score, reasoning} but got: ${jsonText.slice(0, 500)}\\nValidation errors: ${JSON.stringify(result.error.issues)}`\n );\n }\n return result.data;\n}\n","/* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any */\nimport type { Judge, JudgeConfig, JudgeResult } from './judgeTypes.js';\nimport { JudgeResponseSchema } from './judgeTypes.js';\n\n/**\n * Creates an OpenAI-backed LLM judge.\n * Requires the `openai` package and an OpenAI API key.\n */\nexport function createOpenAIJudge(config: JudgeConfig = {}): Judge {\n const apiKeyEnvVar = config.apiKeyEnvVar ?? 'OPENAI_API_KEY';\n const apiKey = process.env[apiKeyEnvVar];\n if (!apiKey) {\n throw new Error(\n `OpenAI judge requires an API key. Set the ${apiKeyEnvVar} environment variable.`\n );\n }\n\n const model = config.model ?? 'gpt-4o';\n const maxTokens = config.maxTokens ?? 1000;\n const temperature = config.temperature ?? 0.0;\n\n return {\n async evaluate(candidate, reference, rubric): Promise<JudgeResult> {\n // Dynamic import keeps `openai` an optional runtime dep.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let openaiModule: any;\n try {\n // @ts-expect-error - optional: npm install openai\n openaiModule = await import('openai');\n } catch (err) {\n throw new Error(\n 'OpenAI judge requires the `openai` package. Install it with: npm install openai\\n' +\n `Original error: ${err instanceof Error ? err.message : String(err)}`\n );\n }\n\n const client = new openaiModule.default({ apiKey });\n const prompt = buildJudgePrompt(candidate, reference, rubric);\n\n const startTime = Date.now();\n const completion = await client.chat.completions.create({\n model,\n max_tokens: maxTokens,\n temperature,\n messages: [\n {\n role: 'system',\n content:\n 'You are an expert evaluator. Respond with valid JSON only: {\"pass\": true|false, \"score\": 0.0-1.0, \"reasoning\": \"explanation\"}',\n },\n { role: 'user', content: prompt },\n ],\n });\n const durationMs = Date.now() - startTime;\n\n const text =\n (completion.choices[0]?.message.content as string | null | undefined) ??\n '';\n const parsed = parseJudgeResponse(text);\n\n return {\n pass: parsed.pass,\n score: parsed.score,\n reasoning: parsed.reasoning,\n usage: {\n inputTokens:\n (completion.usage?.prompt_tokens as number | undefined) ?? 0,\n outputTokens:\n (completion.usage?.completion_tokens as number | undefined) ?? 0,\n totalCostUsd: 0,\n durationMs,\n },\n };\n },\n };\n}\n\nfunction buildJudgePrompt(\n candidate: unknown,\n reference: unknown,\n rubric: string\n): string {\n const candidateStr =\n typeof candidate === 'string'\n ? candidate\n : JSON.stringify(candidate, null, 2);\n\n const referenceStr =\n reference !== null && reference !== undefined\n ? typeof reference === 'string'\n ? reference\n : JSON.stringify(reference, null, 2)\n : null;\n\n return (\n `Rubric:\\n${rubric}\\n\\n` +\n `<candidate_response>\\n${candidateStr}\\n</candidate_response>\\n\\n` +\n `<reference_answer>\\n${referenceStr ?? 'No reference provided.'}\\n</reference_answer>\\n\\n` +\n `Evaluate and return JSON: {\"pass\": boolean, \"score\": number (0-1), \"reasoning\": string}`\n );\n}\n\nfunction parseJudgeResponse(text: string): {\n pass: boolean;\n score: number;\n reasoning: string;\n} {\n const cleaned = text\n .replace(/```json\\n?/g, '')\n .replace(/```\\n?/g, '')\n .trim();\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(cleaned);\n } catch {\n throw new Error(`Failed to parse judge response as JSON: ${text}`);\n }\n\n const result = JudgeResponseSchema.safeParse(parsed);\n if (!result.success) {\n throw new Error(\n `Judge returned invalid response. Expected {pass, score, reasoning} but got: ${cleaned.slice(0, 500)}\\nValidation errors: ${JSON.stringify(result.error.issues)}`\n );\n }\n return result.data;\n}\n","/* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any */\nimport type { Judge, JudgeConfig, JudgeResult } from './judgeTypes.js';\nimport { JudgeResponseSchema } from './judgeTypes.js';\n\n/**\n * Creates a Google Gemini-backed LLM judge.\n * Requires the `@google/generative-ai` package and a Google API key.\n */\nexport function createGoogleJudge(config: JudgeConfig = {}): Judge {\n const apiKeyEnvVar = config.apiKeyEnvVar ?? 'GOOGLE_API_KEY';\n const apiKey = process.env[apiKeyEnvVar];\n if (!apiKey) {\n throw new Error(\n `Google judge requires an API key. Set the ${apiKeyEnvVar} environment variable.`\n );\n }\n\n const model = config.model ?? 'gemini-2.0-flash';\n const maxTokens = config.maxTokens ?? 1000;\n\n return {\n async evaluate(candidate, reference, rubric): Promise<JudgeResult> {\n // Dynamic import keeps `@google/generative-ai` an optional runtime dep.\n let googleModule: any;\n try {\n // @ts-expect-error - optional: npm install @google/generative-ai\n googleModule = await import('@google/generative-ai');\n } catch (err) {\n throw new Error(\n 'Google judge requires the `@google/generative-ai` package. Install it with: npm install @google/generative-ai\\n' +\n `Original error: ${err instanceof Error ? err.message : String(err)}`\n );\n }\n\n const genAI = new googleModule.GoogleGenerativeAI(apiKey);\n const gemini = genAI.getGenerativeModel({\n model,\n generationConfig: {\n maxOutputTokens: maxTokens,\n temperature: 0.0,\n },\n systemInstruction:\n 'You are an expert evaluator. Respond with valid JSON only: {\"pass\": true|false, \"score\": 0.0-1.0, \"reasoning\": \"explanation\"}',\n });\n\n const candidateStr =\n typeof candidate === 'string'\n ? candidate\n : JSON.stringify(candidate, null, 2);\n\n const referenceStr =\n reference !== null && reference !== undefined\n ? typeof reference === 'string'\n ? reference\n : JSON.stringify(reference, null, 2)\n : null;\n\n const prompt =\n `Rubric:\\n${rubric}\\n\\n` +\n `<candidate_response>\\n${candidateStr}\\n</candidate_response>\\n\\n` +\n `<reference_answer>\\n${referenceStr ?? 'No reference provided.'}\\n</reference_answer>\\n\\n` +\n `Evaluate and return JSON: {\"pass\": boolean, \"score\": number (0-1), \"reasoning\": string}`;\n\n const startTime = Date.now();\n const result = await gemini.generateContent(prompt);\n const durationMs = Date.now() - startTime;\n\n const text = result.response.text() as string;\n const cleaned = text\n .replace(/```json\\n?/g, '')\n .replace(/```\\n?/g, '')\n .trim();\n\n let parsedRaw: unknown;\n try {\n parsedRaw = JSON.parse(cleaned);\n } catch {\n throw new Error(`Failed to parse judge response as JSON: ${text}`);\n }\n\n const validation = JudgeResponseSchema.safeParse(parsedRaw);\n if (!validation.success) {\n throw new Error(\n `Judge returned invalid response. Expected {pass, score, reasoning} but got: ${cleaned.slice(0, 500)}\\nValidation errors: ${JSON.stringify(validation.error.issues)}`\n );\n }\n const { pass, score, reasoning } = validation.data;\n\n return {\n pass,\n score,\n reasoning,\n usage: {\n inputTokens:\n (result.response.usageMetadata?.promptTokenCount as\n | number\n | undefined) ?? 0,\n outputTokens:\n (result.response.usageMetadata?.candidatesTokenCount as\n | number\n | undefined) ?? 0,\n totalCostUsd: 0,\n durationMs,\n },\n };\n },\n };\n}\n","import type { Judge, JudgeConfig, ProviderKind } from './judgeTypes.js';\nimport { createAnthropicJudge } from './anthropicJudge.js';\nimport { createVertexAnthropicJudge } from './vertexAnthropicJudge.js';\nimport { createClaudeAgentJudge } from './claudeAgentJudge.js';\nimport { createOpenAIJudge } from './openaiJudge.js';\nimport { createGoogleJudge } from './googleJudge.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 ?? 'anthropic';\n\n switch (provider) {\n case 'anthropic':\n return createAnthropicJudge(config);\n\n case 'vertex-anthropic':\n return createVertexAnthropicJudge(config);\n\n case 'anthropic-agent-sdk':\n return createClaudeAgentJudge(config);\n\n case 'openai':\n return createOpenAIJudge(config);\n\n case 'google':\n return createGoogleJudge(config);\n\n default:\n throw new Error(`Unsupported LLM provider: ${String(provider)}`);\n }\n}\n","/**\n * Custom Judge Registry\n *\n * Allows consumers to register named judge executors that can be referenced\n * by string ID in eval fixtures and programmatic tests. This enables\n * multi-step judge pipelines (LLM call + post-processing), custom scoring\n * logic, and reusable judge configurations without duplicating rubrics.\n */\n\n/**\n * Result returned by a custom judge executor.\n *\n * Custom judges must return a normalized score (0–1). The framework applies\n * the caller's `threshold` (default 0.7) to determine pass/fail. This keeps\n * judges reusable — the same judge can be used with different thresholds in\n * different tests.\n */\nexport interface CustomJudgeResult {\n /** Normalized score (0–1, where 1 is best) */\n score: number;\n /** Optional reasoning/explanation */\n reasoning?: string;\n}\n\n/**\n * A user-defined judge executor function.\n *\n * Custom executors own their entire evaluation pipeline — prompt construction,\n * LLM calls, and post-processing — but return a normalized score. The framework\n * determines pass/fail by comparing the score against the caller's threshold.\n *\n * @param candidate - The actual response to evaluate\n * @param reference - Optional reference/expected response\n * @returns Evaluation result with a normalized score and optional reasoning\n *\n * @example\n * ```typescript\n * const completenessJudge: CustomJudgeExecutor = async (candidate, reference) => {\n * // Step 1: LLM call with your own prompt and schema\n * const llmResult = await callLLM(COMPLETENESS_PROMPT, candidate);\n * const { verdict, reasoning } = JSON.parse(llmResult);\n *\n * // Step 2: Deterministic post-processing into a normalized score\n * const score = { Complete: 1.0, Incomplete: 0.5 }[verdict] ?? 0.0;\n *\n * return { score, reasoning };\n * };\n * ```\n */\nexport type CustomJudgeExecutor = (\n candidate: unknown,\n reference?: unknown\n) => Promise<CustomJudgeResult>;\n\nconst registry = new Map<string, CustomJudgeExecutor>();\n\n/**\n * Registers a named custom judge executor.\n *\n * Call this in your test setup (e.g., `playwright.config.ts` or a global setup file)\n * before tests run. The name can then be referenced in JSON eval fixtures via the\n * `judge` field on `passesJudge`.\n *\n * @param name - Unique identifier for the judge\n * @param executor - The judge executor function\n * @throws {Error} If a judge with the same name is already registered\n *\n * @example\n * ```typescript\n * import { registerJudge } from '@gleanwork/mcp-server-tester';\n *\n * registerJudge('glean-completeness', async (candidate, reference) => {\n * // Step 1: LLM call with your own prompt and schema\n * const llmResult = await callLLM(COMPLETENESS_PROMPT, candidate);\n * const { verdict, reasoning } = JSON.parse(llmResult);\n *\n * // Step 2: Deterministic post-processing into a normalized score\n * const score = { Complete: 1.0, Incomplete: 0.5 }[verdict] ?? 0.0;\n *\n * return { score, reasoning };\n * });\n *\n * // Then in tests — same judge, different thresholds:\n * // expect(result).toPassToolJudge({ judge: 'glean-completeness', passingThreshold: 0.8 });\n * // expect(result).toPassToolJudge({ judge: 'glean-completeness', passingThreshold: 0.5 });\n * ```\n */\nexport function registerJudge(\n name: string,\n executor: CustomJudgeExecutor\n): void {\n const existing = registry.get(name);\n if (existing !== undefined) {\n if (existing === executor) {\n return; // same function re-registered (e.g., shared setup imported by multiple files)\n }\n throw new Error(\n `Judge \"${name}\" is already registered with a different executor. ` +\n `Use clearJudgeRegistry() first if you need to replace it.`\n );\n }\n registry.set(name, executor);\n}\n\n/**\n * Retrieves a registered custom judge executor by name.\n *\n * @param name - The judge name to look up\n * @returns The registered executor\n * @throws {Error} If no judge with the given name is registered\n */\nexport function getRegisteredJudge(name: string): CustomJudgeExecutor {\n const executor = registry.get(name);\n if (!executor) {\n const available =\n registry.size > 0\n ? ` Available judges: ${[...registry.keys()].join(', ')}`\n : ' No judges are registered.';\n throw new Error(\n `Judge \"${name}\" is not registered.${available} ` +\n `Register it with registerJudge() before tests run.`\n );\n }\n return executor;\n}\n\n/**\n * Clears all registered judges. Intended for test teardown.\n */\nexport function clearJudgeRegistry(): void {\n registry.clear();\n}\n","/**\n * Judge Validator\n *\n * Validates a response using an LLM-as-a-judge evaluation.\n */\n\nimport type { ValidationResult } from './types.js';\nimport type { ProviderKind } from '../../judge/judgeTypes.js';\nimport type { RubricSpec } from '../../judge/rubrics.js';\nimport { createJudge } from '../../judge/judgeClient.js';\nimport { resolveRubric } from '../../judge/rubrics.js';\nimport { getRegisteredJudge } from '../../judge/judgeRegistry.js';\n\n/**\n * Configuration for the judge validator\n */\nexport interface JudgeValidatorConfig {\n /**\n * The evaluation rubric: a built-in name or custom { text: string }.\n * Required when no named `judge` is specified.\n */\n rubric?: RubricSpec;\n /** Optional reference response to compare against */\n reference?: unknown;\n /** Minimum score required to pass (0-1, default: 0.7) */\n threshold?: number;\n /** Number of judge evaluations to run. Scores averaged. @default 1 */\n reps?: number;\n /** Judge provider. @default 'claude' */\n provider?: ProviderKind;\n /** Model override (e.g., 'claude-opus-4-20250514') */\n model?: string;\n /** Environment variable name for API key */\n apiKeyEnvVar?: string;\n /** Max tokens for judge response */\n maxTokens?: number;\n /** Temperature for judge LLM (0–1) */\n temperature?: number;\n /** Max budget in USD per evaluation */\n maxBudgetUsd?: number;\n /** Fail if response exceeds this size in bytes before judging */\n maxToolOutputSize?: number;\n /**\n * Name of a registered custom judge executor.\n * When set, the named judge handles the entire evaluation pipeline\n * and returns a normalized score. The `threshold` determines pass/fail.\n * Register judges with `registerJudge()` before tests run.\n */\n judge?: string;\n}\n\n/**\n * Validates a response using an LLM-as-a-judge evaluation\n *\n * Calls the configured judge with the response and rubric, then checks whether\n * the resulting score meets the threshold. Returns a ValidationResult compatible\n * with the unified assertion architecture.\n *\n * @param response - The response to evaluate\n * @param config - Judge evaluation configuration (rubric, reference, threshold, provider, model, etc.)\n * @returns Validation result indicating pass/fail with judge reasoning\n *\n * @example\n * ```typescript\n * const result = await validateJudge(\n * response,\n * { rubric: 'Does the response accurately describe the weather?' }\n * );\n * if (!result.pass) {\n * console.log(result.message);\n * }\n *\n * // With inline judge config and threshold\n * const result2 = await validateJudge(\n * response,\n * { rubric: 'Is this helpful?', threshold: 0.9, model: 'claude-opus-4-20250514', temperature: 0 }\n * );\n * ```\n */\n/**\n * Computes population standard deviation of an array of scores.\n * Returns 0 when there are fewer than 2 values.\n */\nfunction computeStdDev(scores: number[], mean: number): number {\n if (scores.length <= 1) return 0;\n const variance =\n scores.reduce((sum, s) => sum + (s - mean) ** 2, 0) / scores.length;\n return Math.sqrt(variance);\n}\n\nexport async function validateJudge(\n response: unknown,\n config: JudgeValidatorConfig\n): Promise<ValidationResult> {\n const {\n judge: judgeName,\n rubric,\n reference,\n threshold = 0.7,\n reps = 1,\n provider,\n model,\n apiKeyEnvVar,\n maxTokens,\n temperature,\n maxBudgetUsd,\n maxToolOutputSize,\n } = config;\n\n // Named custom judge — executor returns a score, threshold determines pass/fail\n if (judgeName !== undefined) {\n try {\n const executor = getRegisteredJudge(judgeName);\n const judgeResult = await executor(response, reference ?? undefined);\n\n const score = judgeResult.score;\n const passed = score >= threshold;\n\n return {\n pass: passed,\n message: passed\n ? `Custom judge \"${judgeName}\" passed with score ${score.toFixed(2)}`\n : `Custom judge \"${judgeName}\" failed with score ${score.toFixed(2)} (threshold: ${threshold}). ${judgeResult.reasoning ?? ''}`,\n };\n } catch (err) {\n return {\n pass: false,\n message: `Custom judge \"${judgeName}\" error: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n }\n\n // Built-in LLM judge — requires rubric\n if (rubric === undefined) {\n return {\n pass: false,\n message:\n 'Judge evaluation failed: either \"judge\" or \"rubric\" must be provided',\n };\n }\n\n const resolvedRubric = resolveRubric(rubric);\n\n const judgeConfig = {\n ...(provider !== undefined && { provider }),\n ...(model !== undefined && { model }),\n ...(apiKeyEnvVar !== undefined && { apiKeyEnvVar }),\n ...(maxTokens !== undefined && { maxTokens }),\n ...(temperature !== undefined && { temperature }),\n ...(maxBudgetUsd !== undefined && { maxBudgetUsd }),\n ...(maxToolOutputSize !== undefined && { maxToolOutputSize }),\n };\n\n try {\n const judge = createJudge(judgeConfig);\n\n const scores: number[] = [];\n let lastReasoning: string | undefined;\n\n for (let i = 0; i < reps; i++) {\n const judgeResult = await judge.evaluate(\n response,\n reference ?? null,\n resolvedRubric\n );\n scores.push(judgeResult.score ?? (judgeResult.pass ? 1.0 : 0.0));\n lastReasoning = judgeResult.reasoning;\n }\n\n if (scores.length === 0) {\n return {\n pass: false,\n message: 'Judge evaluation failed: no scores collected',\n };\n }\n\n const meanScore = scores.reduce((a, b) => a + b, 0) / scores.length;\n const passed = meanScore >= threshold;\n const repNote =\n reps > 1\n ? ` (mean of ${reps} reps: [${scores.map((s) => s.toFixed(2)).join(', ')}])`\n : '';\n\n let stdDev: number | undefined;\n let highVariance: boolean | undefined;\n\n if (reps > 1) {\n stdDev = computeStdDev(scores, meanScore);\n highVariance = stdDev > 0.2;\n\n if (highVariance) {\n console.warn(\n `[mcp-server-tester] Judge scores have high variance ` +\n `(stdDev=${stdDev.toFixed(2)}, scores=[${scores.map((s) => s.toFixed(2)).join(', ')}]). ` +\n `The rubric may be ambiguous.`\n );\n }\n }\n\n return {\n pass: passed,\n message: passed\n ? `Judge passed with score ${meanScore.toFixed(2)}${repNote}`\n : `Judge failed with score ${meanScore.toFixed(2)} (threshold: ${threshold})${repNote}. ${lastReasoning ?? ''}`,\n details: {\n score: meanScore,\n reasoning: lastReasoning,\n judgeProvider: provider ?? 'anthropic',\n judgeModel: model,\n ...(reps > 1 && {\n scores,\n scoreStdDev: stdDev,\n highVariance,\n }),\n },\n };\n } catch (err) {\n return {\n pass: false,\n message: `Judge evaluation error: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n}\n","/**\n * toPassToolJudge Matcher\n *\n * Validates that a response passes LLM-as-judge evaluation.\n * Delegates evaluation logic to validateJudge() for consistency\n * with the validator/matcher duality pattern.\n *\n * Supports three call signatures:\n * - toPassToolJudge(rubric, options?) — built-in LLM judge with rubric\n * - toPassToolJudge({ judge: 'name', ... }) — named custom judge\n * - toPassToolJudge([...judges]) — multi-judge (all must pass)\n */\n\nimport { validateJudge } from '../validators/judge.js';\nimport type { RubricSpec } from '../../judge/rubrics.js';\nimport type { JudgeMatcherOptions } from './types.js';\n\n// Default passing threshold\nconst DEFAULT_PASSING_THRESHOLD = 0.7;\n\n/**\n * Runs a single judge evaluation and returns the result.\n */\nasync function runSingleJudge(\n received: unknown,\n rubric: RubricSpec | undefined,\n options: JudgeMatcherOptions\n): Promise<{ pass: boolean; message: string }> {\n const {\n reference = null,\n passingThreshold = DEFAULT_PASSING_THRESHOLD,\n reps,\n provider,\n model,\n judge,\n } = options;\n\n const validation = await validateJudge(received, {\n ...(rubric !== undefined && { rubric }),\n reference: reference ?? undefined,\n threshold: passingThreshold,\n ...(reps !== undefined && { reps }),\n ...(provider !== undefined && { provider }),\n ...(model !== undefined && { model }),\n ...(judge !== undefined && { judge }),\n });\n\n return { pass: validation.pass, message: validation.message };\n}\n\n/**\n * The toPassToolJudge matcher function.\n *\n * Accepts either:\n * (received, rubric, options?) — rubric-based LLM judge\n * (received, options) — named custom judge (options.judge required)\n * (received, judges[]) — multi-judge (all must pass)\n */\nexport async function toPassToolJudge(\n this: { isNot: boolean },\n received: unknown,\n rubricOrOptions:\n | RubricSpec\n | JudgeMatcherOptions\n | Array<JudgeMatcherOptions & { rubric?: RubricSpec }>,\n maybeOptions?: JudgeMatcherOptions\n): Promise<{ pass: boolean; message: () => string }> {\n // Multi-judge: array of judge configs\n if (Array.isArray(rubricOrOptions)) {\n const results = await Promise.all(\n rubricOrOptions.map(async (judgeConfig) => {\n const { rubric: r, ...opts } = judgeConfig;\n return runSingleJudge(received, r, opts);\n })\n );\n\n const allPassed = results.every((r) => r.pass);\n const passCount = results.filter((r) => r.pass).length;\n const summary = `${passCount}/${results.length} judges passed`;\n const details = results.map((r) => r.message).join('\\n');\n\n if (this.isNot) {\n return {\n pass: !allPassed,\n message: () =>\n allPassed\n ? `Expected all judges to fail, but ${summary}`\n : `Judges failed as expected: ${summary}`,\n };\n }\n\n return {\n pass: allPassed,\n message: () => `${summary}\\n${details}`,\n };\n }\n\n // Single judge\n let rubric: RubricSpec | undefined;\n let options: JudgeMatcherOptions;\n\n if (\n typeof rubricOrOptions === 'string' ||\n (typeof rubricOrOptions === 'object' &&\n rubricOrOptions !== null &&\n 'text' in rubricOrOptions)\n ) {\n rubric = rubricOrOptions as RubricSpec;\n options = maybeOptions ?? {};\n } else {\n options = rubricOrOptions;\n }\n\n const result = await runSingleJudge(received, rubric, options);\n\n if (this.isNot) {\n return {\n pass: !result.pass,\n message: () =>\n result.pass\n ? `Expected judge evaluation to fail, but it passed`\n : `Judge evaluation failed as expected`,\n };\n }\n\n return {\n pass: result.pass,\n message: () => result.message,\n };\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","/**\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 * Tool call validators for mcp_host simulation results.\n *\n * These validators extract the tool call trace from an MCPHostSimulationResult\n * and apply assertions against expected call lists and counts.\n */\nimport type { ValidationResult } from './types.js';\nimport type {\n MCPHostSimulationResult,\n LLMToolCall,\n} from '../../evals/mcpHost/mcpHostTypes.js';\n\nexport interface ToolCallExpectation {\n calls: Array<{\n name: string;\n arguments?: Record<string, unknown>;\n required?: boolean;\n }>;\n order?: 'strict' | 'any';\n exclusive?: boolean;\n}\n\nexport interface ToolCallCountOptions {\n min?: number;\n max?: number;\n exact?: number;\n}\n\nfunction isSimulationResult(value: unknown): value is MCPHostSimulationResult {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'success' in value &&\n 'toolCalls' in value &&\n Array.isArray((value as MCPHostSimulationResult).toolCalls)\n );\n}\n\n/**\n * Checks whether a value is a `{ $pattern: \"regex\" }` matcher object.\n */\nfunction isPatternMatcher(\n v: unknown\n): v is { $pattern: string; $flags?: string } {\n return (\n typeof v === 'object' &&\n v !== null &&\n '$pattern' in v &&\n typeof (v as Record<string, unknown>)['$pattern'] === 'string'\n );\n}\n\nfunction partialMatch(\n actual: Record<string, unknown>,\n expected: Record<string, unknown>\n): boolean {\n return Object.entries(expected).every(([k, v]) => {\n const actualVal = actual[k];\n\n // { $pattern: \"regex\", $flags?: \"i\" } — match actual string against regex\n if (isPatternMatcher(v)) {\n if (typeof actualVal !== 'string') return false;\n const re = new RegExp(v.$pattern, v.$flags);\n return re.test(actualVal);\n }\n\n if (\n typeof v === 'object' &&\n v !== null &&\n typeof actualVal === 'object' &&\n actualVal !== null\n ) {\n return partialMatch(\n actualVal as Record<string, unknown>,\n v as Record<string, unknown>\n );\n }\n // Key order in nested objects is handled by recursion — this branch only\n // reaches leaf primitives (strings, numbers, booleans, null) and arrays,\n // where JSON.stringify comparison is correct.\n return JSON.stringify(actualVal) === JSON.stringify(v);\n });\n}\n\nfunction findMatchingCall(\n actual: LLMToolCall[],\n expected: ToolCallExpectation['calls'][number],\n startIndex = 0\n): number {\n for (let i = startIndex; i < actual.length; i++) {\n const call = actual[i]!;\n if (call.name !== expected.name) continue;\n if (\n expected.arguments !== undefined &&\n !partialMatch(call.arguments ?? {}, expected.arguments)\n ) {\n continue;\n }\n return i;\n }\n return -1;\n}\n\n/**\n * Validates tool calls made during an MCP host simulation.\n *\n * @param response - Must be an MCPHostSimulationResult (from mcp_host mode)\n * @param expectation - Expected tool call specification\n */\nexport function validateToolCalls(\n response: unknown,\n expectation: ToolCallExpectation\n): ValidationResult {\n if (!isSimulationResult(response)) {\n return {\n pass: false,\n message:\n 'toolsTriggered expectation requires mcp_host mode — response must be an MCPHostSimulationResult',\n };\n }\n\n const actual = response.toolCalls;\n\n // Compute recall: fraction of required calls that were made\n const requiredCalls = expectation.calls.filter((c) => c.required !== false);\n const calledRequiredCount = requiredCalls.filter(\n (expected) => findMatchingCall(actual, expected) !== -1\n ).length;\n const recall =\n requiredCalls.length > 0 ? calledRequiredCount / requiredCalls.length : 1.0;\n\n // Compute precision: fraction of actual calls that were expected.\n // Always computed so the metric reflects actual tool call efficiency.\n // Whether unexpected calls cause a FAILURE is controlled separately by exclusive=true (lines below).\n const allowedNames = new Set(expectation.calls.map((c) => c.name));\n const precision =\n actual.length > 0\n ? actual.filter((c) => allowedNames.has(c.name)).length / actual.length\n : 1.0;\n\n const metrics = { precision, recall };\n\n const order = expectation.order ?? 'any';\n\n if (order === 'strict') {\n // All calls must appear in the specified sequence\n let searchFrom = 0;\n for (const expected of expectation.calls) {\n const idx = findMatchingCall(actual, expected, searchFrom);\n if (idx === -1) {\n if (expected.required !== false) {\n return {\n pass: false,\n message: `Expected tool '${expected.name}' to be called in sequence (starting from position ${searchFrom}), but it was not found`,\n metrics,\n };\n }\n } else {\n searchFrom = idx + 1;\n }\n }\n } else {\n // Any order: each required call must appear somewhere\n const required = expectation.calls.filter((c) => c.required !== false);\n for (const expected of required) {\n const idx = findMatchingCall(actual, expected);\n if (idx === -1) {\n const argsNote =\n expected.arguments !== undefined\n ? ` with args ${JSON.stringify(expected.arguments)}`\n : '';\n return {\n pass: false,\n message: `Expected tool '${expected.name}'${argsNote} to be called, but it was not`,\n metrics,\n };\n }\n }\n }\n\n if (expectation.exclusive === true) {\n const unexpected = actual.filter((c) => !allowedNames.has(c.name));\n if (unexpected.length > 0) {\n const names = unexpected.map((c) => `'${c.name}'`).join(', ');\n return {\n pass: false,\n message: `Unexpected tool calls: ${names}. Only ${[...allowedNames].map((n) => `'${n}'`).join(', ')} are allowed`,\n metrics,\n };\n }\n }\n\n return { pass: true, message: 'All tool call expectations met', metrics };\n}\n\n/**\n * Validates the number of tool calls made during an MCP host simulation.\n *\n * @param response - Must be an MCPHostSimulationResult (from mcp_host mode)\n * @param options - Count constraints (min, max, exact)\n */\nexport function validateToolCallCount(\n response: unknown,\n options: ToolCallCountOptions\n): ValidationResult {\n if (!isSimulationResult(response)) {\n return {\n pass: false,\n message:\n 'toolCallCount expectation requires mcp_host mode — response must be an MCPHostSimulationResult',\n };\n }\n\n const count = response.toolCalls.length;\n const { min, max, exact } = options;\n\n if (exact !== undefined && count !== exact) {\n return {\n pass: false,\n message: `Expected exactly ${exact} tool call(s), but got ${count}`,\n };\n }\n\n if (min !== undefined && count < min) {\n return {\n pass: false,\n message: `Expected at least ${min} tool call(s), but got ${count}`,\n };\n }\n\n if (max !== undefined && count > max) {\n return {\n pass: false,\n message: `Expected at most ${max} tool call(s), but got ${count}`,\n };\n }\n\n return {\n pass: true,\n message: `Tool call count (${count}) is within expected range`,\n };\n}\n","/**\n * toHaveToolCalls Matcher\n *\n * Validates which tools the LLM called during a mcp_host simulation.\n */\n\nimport { validateToolCalls } from '../validators/toolCalls.js';\nimport type { ToolCallExpectation } from '../validators/toolCalls.js';\n\n/**\n * Creates the toHaveToolCalls matcher function\n */\nexport function toHaveToolCalls(\n this: { isNot: boolean },\n received: unknown,\n expectation: ToolCallExpectation\n) {\n const result = validateToolCalls(received, expectation);\n\n return {\n pass: result.pass,\n message: () => result.message,\n };\n}\n","/**\n * toHaveToolCallCount Matcher\n *\n * Validates the number of tool calls made during a mcp_host simulation.\n */\n\nimport { validateToolCallCount } from '../validators/toolCalls.js';\nimport type { ToolCallCountOptions } from '../validators/toolCalls.js';\n\n/**\n * Creates the toHaveToolCallCount matcher function\n */\nexport function toHaveToolCallCount(\n this: { isNot: boolean },\n received: unknown,\n options: ToolCallCountOptions\n) {\n const result = validateToolCallCount(received, options);\n\n return {\n pass: result.pass,\n message: () => result.message,\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';\nimport { toHaveToolCalls } from './toHaveToolCalls.js';\nimport { toHaveToolCallCount } from './toHaveToolCallCount.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 '@gleanwork/mcp-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 toHaveToolCalls,\n toHaveToolCallCount,\n});\n\n// Re-export types\nexport type {\n JudgeMatcherOptions,\n ToolPredicate,\n PredicateResult,\n} from './types.js';\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 * OAuth 2.1 client credentials configuration for machine-to-machine (CI/CD) authentication.\n * Credentials can be provided here or via MCP_CLIENT_ID/MCP_CLIENT_SECRET environment variables.\n */\nexport interface MCPClientCredentialsConfig {\n /**\n * OAuth client ID (falls back to MCP_CLIENT_ID env var)\n */\n clientId?: string;\n\n /**\n * OAuth client secret (falls back to MCP_CLIENT_SECRET env var)\n */\n clientSecret?: string;\n\n /**\n * Token endpoint URL (required)\n */\n tokenEndpoint?: string;\n\n /**\n * Scopes to request\n */\n scopes?: 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 * OAuth 2.1 client credentials grant for machine-to-machine authentication\n */\n clientCredentials?: MCPClientCredentialsConfig;\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 via stdio transport (local process)\n */\nexport interface StdioMCPConfig {\n /**\n * Transport type discriminant\n */\n transport: 'stdio';\n\n /**\n * Command to execute (required for stdio transport)\n */\n command: string;\n\n /**\n * Command arguments\n */\n args?: Array<string>;\n\n /**\n * Working directory for the command\n */\n cwd?: string;\n\n /**\n * Environment variables to pass to the subprocess.\n * Merged with the current process environment.\n */\n env?: Record<string, string>;\n\n /**\n * Suppress stderr output from the server process.\n * When true, server stderr is ignored instead of inherited.\n */\n quiet?: boolean;\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 * Timeout in milliseconds for MCP tool/list operations. Default: 30000\n */\n callTimeoutMs?: number;\n}\n\n/**\n * Configuration for MCP client connection via HTTP transport (remote server)\n */\nexport interface HttpMCPConfig {\n /**\n * Transport type discriminant\n */\n transport: 'http';\n\n /**\n * Server URL (required for http transport)\n */\n serverUrl: string;\n\n /**\n * HTTP headers (e.g., Authorization)\n */\n headers?: Record<string, string>;\n\n /**\n * Authentication configuration\n */\n auth?: MCPAuthConfig;\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 * Timeout in milliseconds for MCP tool/list operations. Default: 30000\n */\n callTimeoutMs?: number;\n\n /**\n * HTTP proxy configuration. Falls back to HTTPS_PROXY/HTTP_PROXY environment variables.\n */\n proxy?: {\n /**\n * Proxy URL. Credentials can be embedded directly if required:\n * `http://user:pass@proxy.example.com:8080`\n */\n url: string;\n };\n\n /**\n * Number of retry attempts for transient connection failures and 429 rate limit responses.\n * Uses exponential backoff with Retry-After header awareness. Defaults to 0 (no retries).\n */\n retryAttempts?: number;\n\n /**\n * TLS/mTLS configuration for custom certificates or disabling cert validation.\n * File paths should point to PEM-encoded certificate files.\n */\n tls?: {\n /**\n * Path to CA certificate PEM file (for custom/self-signed CAs)\n */\n ca?: string;\n\n /**\n * Path to client certificate PEM file (for mutual TLS)\n */\n cert?: string;\n\n /**\n * Path to client private key PEM file (for mutual TLS)\n */\n key?: string;\n\n /**\n * Whether to reject unauthorized certificates. Defaults to true.\n * Set to false to disable certificate validation (not recommended for production).\n */\n rejectUnauthorized?: boolean;\n };\n}\n\n/**\n * Configuration for MCP client connection.\n *\n * This is a discriminated union — narrow with `isStdioConfig()` or `isHttpConfig()`\n * before accessing transport-specific fields.\n *\n * Supports both stdio (local) and HTTP (remote) transports.\n */\nexport type MCPConfig = StdioMCPConfig | HttpMCPConfig;\n\n/**\n * Zod schema for MCPHostCapabilities\n */\nconst MCPHostCapabilitiesSchema = z.object({\n sampling: z.record(z.string(), 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 MCPClientCredentialsConfig\n */\nconst MCPClientCredentialsConfigSchema = z.object({\n clientId: z.string().optional(),\n clientSecret: z.string().optional(),\n tokenEndpoint: z.string().url('tokenEndpoint must be a valid URL').optional(),\n scopes: z.array(z.string()).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 clientCredentials: MCPClientCredentialsConfigSchema.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 env: z.record(z.string(), z.string()).optional(),\n capabilities: MCPHostCapabilitiesSchema.optional(),\n connectTimeoutMs: z.number().positive().optional(),\n requestTimeoutMs: z.number().positive().optional(),\n callTimeoutMs: z.number().positive().optional(),\n quiet: z.boolean().optional(),\n});\n\n/**\n * Returns true if the hostname refers to the loopback interface\n */\nfunction isLocalhost(hostname: string): boolean {\n return (\n hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '::1'\n );\n}\n\n/**\n * Zod schema for HTTP transport config\n */\nconst HttpConfigSchema = z.object({\n transport: z.literal('http'),\n serverUrl: z\n .string()\n .url('serverUrl must be a valid URL')\n .refine((url) => {\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n return true;\n }\n if (parsed.protocol === 'http:' && !isLocalhost(parsed.hostname)) {\n console.warn(\n `[mcp-server-tester] serverUrl uses http:// for non-localhost address \"${parsed.hostname}\". ` +\n `This transmits tokens unencrypted. Use https:// for remote servers.`\n );\n }\n return true;\n }),\n headers: z.record(z.string(), z.string()).optional(),\n capabilities: MCPHostCapabilitiesSchema.optional(),\n connectTimeoutMs: z.number().positive().optional(),\n requestTimeoutMs: z.number().positive().optional(),\n callTimeoutMs: z.number().positive().optional(),\n auth: MCPAuthConfigSchema.optional(),\n proxy: z\n .object({\n url: z.string().url('proxy.url must be a valid URL'),\n })\n .optional(),\n retryAttempts: z.number().int().min(0).optional(),\n tls: z\n .object({\n ca: z.string().optional(),\n cert: z.string().optional(),\n key: z.string().optional(),\n rejectUnauthorized: z.boolean().optional(),\n })\n .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(config: MCPConfig): config is StdioMCPConfig {\n return config.transport === 'stdio';\n}\n\n/**\n * Type guard to check if a config is for HTTP transport\n */\nexport function isHttpConfig(config: MCPConfig): config is HttpMCPConfig {\n return config.transport === 'http';\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-server-tester logs\n * DEBUG=mcp-server-tester:* npm test\n *\n * # Enable only client logs\n * DEBUG=mcp-server-tester:client npm test\n *\n * # Enable only OAuth logs\n * DEBUG=mcp-server-tester:oauth npm test\n *\n * # Enable HTTP-level trace logging (URL, headers, transport selection)\n * DEBUG=mcp-server-tester:http npx playwright test\n * ```\n */\n\nimport createDebug from 'debug';\n\nconst NAMESPACE = 'mcp-server-tester';\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/**\n * Debug logger for HTTP-level trace logging.\n *\n * Enable with:\n * ```bash\n * DEBUG=mcp-server-tester:http npx playwright test\n * ```\n *\n * Logs: server URL, transport type selected (Streamable HTTP vs SSE),\n * outgoing request header names, and connection outcomes.\n */\nexport const debugHttp = createDebug(`${NAMESPACE}:http`);\n","{\n \"name\": \"@gleanwork/mcp-server-tester\",\n \"version\": \"1.0.0-beta.8\",\n \"description\": \"Playwright-based testing and evaluation framework for MCP servers\",\n \"keywords\": [\n \"playwright\",\n \"mcp\",\n \"model-context-protocol\",\n \"evals\",\n \"testing\",\n \"llm\",\n \"server-testing\"\n ],\n \"homepage\": \"https://github.com/gleanwork/mcp-server-tester#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/gleanwork/mcp-server-tester/issues\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/gleanwork/mcp-server-tester.git\"\n },\n \"license\": \"MIT\",\n \"author\": \"Glean Contributors\",\n \"type\": \"module\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\",\n \"require\": \"./dist/index.cjs\"\n },\n \"./fixtures/mcp\": {\n \"types\": \"./dist/fixtures/mcp.d.ts\",\n \"import\": \"./dist/fixtures/mcp.js\"\n },\n \"./fixtures/mcpAuth\": {\n \"types\": \"./dist/fixtures/mcpAuth.d.ts\",\n \"import\": \"./dist/fixtures/mcpAuth.js\"\n },\n \"./reporters/mcpReporter\": {\n \"types\": \"./dist/reporters/mcpReporter.d.ts\",\n \"import\": \"./dist/reporters/mcpReporter.js\",\n \"require\": \"./dist/reporters/mcpReporter.cjs\"\n }\n },\n \"main\": \"./dist/index.js\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"bin\": {\n \"mcp-server-tester\": \"./dist/cli/index.js\"\n },\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"build\": \"npm run build:ui && tsup && npm run build:copy-ui\",\n \"build:copy-ui\": \"cp -r src/reporters/ui-dist dist/reporters/\",\n \"build:ui\": \"tsx src/reporters/build-ui.ts\",\n \"dev\": \"tsup --watch\",\n \"dev:ui\": \"tsx src/reporters/build-ui.ts --watch\",\n \"format\": \"prettier --write \\\"**/*.{ts,tsx,json,md}\\\"\",\n \"format:check\": \"prettier --check \\\"**/*.{ts,tsx,json,md}\\\"\",\n \"lint\": \"eslint . --ext .ts,.tsx\",\n \"lint:fix\": \"eslint . --ext .ts,.tsx --fix\",\n \"prepublishOnly\": \"npm run test:all\",\n \"docs:check\": \"markdown-code check\",\n \"docs:sync\": \"markdown-code sync\",\n \"preview-reporter\": \"tsx scripts/preview-reporter.ts\",\n \"test\": \"vitest run\",\n \"test:all\": \"npm run build && npm run format:check && npm run lint && npm run typecheck && npm test\",\n \"test:playwright\": \"playwright test\",\n \"test:watch\": \"vitest\",\n \"typecheck\": \"tsc --noEmit\"\n },\n \"dependencies\": {\n \"@anthropic-ai/claude-agent-sdk\": \"^0.2.71\",\n \"@inkjs/ui\": \"^2.0.0\",\n \"@modelcontextprotocol/sdk\": \"^1.27.1\",\n \"commander\": \"^14.0.2\",\n \"debug\": \"^4.4.3\",\n \"ink\": \"^5.2.1\",\n \"ink-spinner\": \"^5.0.0\",\n \"oauth4webapi\": \"^3.0.0\",\n \"open\": \"^10.1.0\",\n \"react\": \"^18.3.1\",\n \"undici\": \"^7.24.0\",\n \"zod\": \"^4.3.6\"\n },\n \"devDependencies\": {\n \"@ai-sdk/provider-utils\": \"^4.0.15\",\n \"@playwright/test\": \"^1.49.0\",\n \"@release-it-plugins/lerna-changelog\": \"^8.0.1\",\n \"@types/debug\": \"^4.1.12\",\n \"@types/node\": \"^22.10.2\",\n \"@types/react\": \"^18.3.12\",\n \"@types/react-dom\": \"^18.3.1\",\n \"@typescript-eslint/eslint-plugin\": \"^8.18.2\",\n \"@typescript-eslint/parser\": \"^8.18.2\",\n \"@vitest/ui\": \"^4.1.2\",\n \"autoprefixer\": \"^10.4.20\",\n \"bintastic\": \"^4.0.1\",\n \"esbuild\": \"^0.28.0\",\n \"eslint\": \"^8.57.1\",\n \"ink-testing-library\": \"^4.0.0\",\n \"lucide-react\": \"^0.460.0\",\n \"markdown-code\": \"^0.6.1\",\n \"memfs\": \"^4.51.1\",\n \"postcss\": \"^8.4.49\",\n \"prettier\": \"^3.4.2\",\n \"react-dom\": \"^18.3.1\",\n \"recharts\": \"^3.7.0\",\n \"release-it\": \"^19.2.4\",\n \"tailwindcss\": \"^3.4.15\",\n \"tsup\": \"^8.3.5\",\n \"tsx\": \"^4.19.2\",\n \"typescript\": \"^5.7.2\",\n \"vitest\": \"^4.1.2\"\n },\n \"peerDependencies\": {\n \"@ai-sdk/anthropic\": \"^3.0.46\",\n \"@ai-sdk/azure\": \"^3.0.0\",\n \"@ai-sdk/deepseek\": \"^2.0.0\",\n \"@ai-sdk/google\": \"^3.0.0\",\n \"@ai-sdk/google-vertex\": \"^4.0.0\",\n \"@ai-sdk/mistral\": \"^3.0.0\",\n \"@ai-sdk/openai\": \"^3.0.31\",\n \"@ai-sdk/xai\": \"^3.0.0\",\n \"@openrouter/ai-sdk-provider\": \"^2.0.0\",\n \"@playwright/test\": \"^1.40.0\",\n \"ai\": \"^6.0.0\"\n },\n \"peerDependenciesMeta\": {\n \"ai\": {\n \"optional\": true\n },\n \"@ai-sdk/anthropic\": {\n \"optional\": true\n },\n \"@ai-sdk/azure\": {\n \"optional\": true\n },\n \"@ai-sdk/deepseek\": {\n \"optional\": true\n },\n \"@ai-sdk/google\": {\n \"optional\": true\n },\n \"@ai-sdk/google-vertex\": {\n \"optional\": true\n },\n \"@ai-sdk/mistral\": {\n \"optional\": true\n },\n \"@ai-sdk/openai\": {\n \"optional\": true\n },\n \"@ai-sdk/xai\": {\n \"optional\": true\n },\n \"@openrouter/ai-sdk-provider\": {\n \"optional\": true\n }\n },\n \"engines\": {\n \"node\": \">=22.0.0\"\n },\n \"publishConfig\": {\n \"access\": \"public\",\n \"registry\": \"https://registry.npmjs.org\"\n },\n \"release-it\": {\n \"plugins\": {\n \"@release-it-plugins/lerna-changelog\": {\n \"infile\": \"CHANGELOG.md\",\n \"launchEditor\": true\n }\n },\n \"git\": {\n \"tagName\": \"v${version}\"\n },\n \"github\": {\n \"release\": true,\n \"tokenRef\": \"GITHUB_AUTH\"\n }\n },\n \"optionalDependencies\": {\n \"@ai-sdk/anthropic\": \"^3.0.46\",\n \"@ai-sdk/azure\": \"^3.0.0\",\n \"@ai-sdk/deepseek\": \"^2.0.0\",\n \"@ai-sdk/google\": \"^3.0.0\",\n \"@ai-sdk/google-vertex\": \"^4.0.68\",\n \"@ai-sdk/mistral\": \"^3.0.0\",\n \"@ai-sdk/openai\": \"^3.0.31\",\n \"@ai-sdk/xai\": \"^3.0.0\",\n \"@openrouter/ai-sdk-provider\": \"^2.0.0\",\n \"ai\": \"^6.0.97\"\n },\n \"overrides\": {\n \"release-it\": {\n \"undici\": \"6.24.1\"\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 createDebug from 'debug';\nimport type { TokenResult } from './types.js';\n\nconst debug = createDebug('mcp-server-tester:oauth-flow');\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 * Configuration for client credentials grant\n */\nexport interface ClientCredentialsConfig {\n /**\n * Token endpoint URL\n */\n tokenEndpoint: string;\n\n /**\n * OAuth client ID\n */\n clientId: string;\n\n /**\n * OAuth client secret\n */\n clientSecret: string;\n\n /**\n * Scopes to request (optional)\n */\n scopes?: string[];\n}\n\n/**\n * Performs the OAuth 2.1 client credentials grant to obtain an access token.\n * Suitable for CI/CD machine-to-machine authentication.\n *\n * Uses oauth4webapi for spec-compliant request construction and response validation,\n * consistent with how the rest of this module handles OAuth flows.\n *\n * @param config - Client credentials configuration\n * @returns Token result\n */\nexport async function performClientCredentialsFlow(\n config: ClientCredentialsConfig\n): Promise<TokenResult> {\n // Construct minimal AuthorizationServer from the token endpoint URL.\n // oauth4webapi requires an issuer; we use the origin of the token endpoint.\n const tokenEndpointUrl = new URL(config.tokenEndpoint);\n const authServer: oauth.AuthorizationServer = {\n issuer: tokenEndpointUrl.origin,\n token_endpoint: config.tokenEndpoint,\n };\n\n const client: oauth.Client = {\n client_id: config.clientId,\n };\n\n // ClientSecretBasic transmits credentials via Authorization: Basic header (RFC 6749 §2.3.1).\n // This is the recommended method — avoids placing secrets in the request body.\n const clientAuth = oauth.ClientSecretBasic(config.clientSecret);\n\n const parameters: Record<string, string> = {};\n if (config.scopes && config.scopes.length > 0) {\n parameters['scope'] = config.scopes.join(' ');\n }\n\n const response = await oauth.clientCredentialsGrantRequest(\n authServer,\n client,\n clientAuth,\n parameters\n );\n\n const result = await oauth.processClientCredentialsResponse(\n authServer,\n client,\n response\n );\n\n const requestedScopes = new Set(\n config.scopes && config.scopes.length > 0 ? config.scopes : []\n );\n const grantedScopes = new Set(\n (result.scope ?? '').split(' ').filter(Boolean)\n );\n const missingScopes = [...requestedScopes].filter(\n (s) => !grantedScopes.has(s)\n );\n if (\n missingScopes.length > 0 &&\n requestedScopes.size > 0 &&\n grantedScopes.size > 0\n ) {\n debug(\n '[oauth] Warning: Token server granted fewer scopes than requested. Missing: %s',\n missingScopes.join(', ')\n );\n }\n\n return {\n accessToken: result.access_token,\n tokenType: result.token_type,\n expiresIn: result.expires_in,\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","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 { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.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, debugHttp } from '../debug.js';\nimport { ProxyAgent, Agent as UndiciAgent } from 'undici';\nimport { readFileSync } from 'node:fs';\nimport packageJson from '../../package.json' with { type: 'json' };\nimport { performClientCredentialsFlow } from '../auth/oauthFlow.js';\n\n/**\n * Extracts the Retry-After delay in milliseconds from an error response, if present.\n * Returns null if no Retry-After header is found or parseable.\n */\nfunction getRetryAfterDelayMs(err: unknown): number | null {\n const response = (err as Record<string, unknown>)?.response as\n | Response\n | undefined;\n const retryAfter = response?.headers?.get?.('Retry-After');\n if (retryAfter) {\n const seconds = parseInt(retryAfter, 10);\n if (!isNaN(seconds)) return seconds * 1000;\n }\n return null;\n}\n\n/**\n * Returns true if the error is a 429 rate limit response\n */\nfunction isRateLimitError(err: unknown): boolean {\n const response = (err as Record<string, unknown>)?.response as\n | Response\n | undefined;\n return response?.status === 429;\n}\n\n/**\n * Returns true if the error is a transient network error that may succeed on retry\n */\nfunction isTransientNetworkError(err: unknown): boolean {\n if (!(err instanceof Error)) return false;\n const msg = err.message.toLowerCase();\n return (\n msg.includes('econnreset') ||\n msg.includes('econnrefused') ||\n msg.includes('etimedout') ||\n msg.includes('enotfound') ||\n msg.includes('network') ||\n msg.includes('socket hang up') ||\n msg.includes('fetch failed')\n );\n}\n\n/**\n * Returns true if the error should be retried\n */\nfunction isRetryableError(err: unknown): boolean {\n return isTransientNetworkError(err) || isRateLimitError(err);\n}\n\n/**\n * Retries an async operation with exponential backoff.\n * Respects Retry-After headers for 429 rate limit responses.\n */\nasync function retryWithBackoff<T>(\n fn: () => Promise<T>,\n maxAttempts: number\n): Promise<T> {\n let lastErr: unknown;\n for (let attempt = 0; attempt <= maxAttempts; attempt++) {\n try {\n return await fn();\n } catch (err) {\n lastErr = err;\n if (attempt < maxAttempts && isRetryableError(err)) {\n const retryAfterMs = getRetryAfterDelayMs(err);\n const delayMs =\n retryAfterMs !== null\n ? retryAfterMs\n : Math.min(1000 * 2 ** attempt, 30000);\n debugClient(\n 'Retryable error on attempt %d/%d, retrying in %dms: %s',\n attempt + 1,\n maxAttempts + 1,\n delayMs,\n (err as Error).message\n );\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n } else {\n throw err;\n }\n }\n }\n throw lastErr;\n}\n\n/**\n * Tracks undici agents that need to be closed when their associated client is closed.\n * Keyed by Client instance identity.\n */\nconst agentRegistry = new WeakMap<object, UndiciAgent | ProxyAgent>();\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 * Sampling handler callback for LLM sampling requests from the server.\n *\n * When provided, the client will advertise sampling capability to the server.\n * When absent, sampling is removed from declared capabilities so the client\n * does not falsely advertise support it cannot fulfill.\n */\n samplingHandler?: (...args: unknown[]) => unknown;\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 ?? '@gleanwork/mcp-server-tester',\n version: options?.clientInfo?.version ?? packageJson.version,\n },\n {\n capabilities: {\n ...(validatedConfig.capabilities ?? {}),\n // Only advertise sampling if a handler has been registered;\n // declaring sampling capability without a handler violates the MCP spec\n sampling: options?.samplingHandler\n ? (validatedConfig.capabilities?.sampling ?? {})\n : undefined,\n },\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 ...(validatedConfig.env && {\n env: Object.fromEntries(\n Object.entries({ ...process.env, ...validatedConfig.env }).filter(\n (entry): entry is [string, string] => entry[1] !== undefined\n )\n ),\n }),\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(\n transport,\n validatedConfig.connectTimeoutMs !== undefined\n ? { timeout: validatedConfig.connectTimeoutMs }\n : undefined\n );\n } else if (isHttpConfig(validatedConfig)) {\n // Build headers, including static token auth if configured and no authProvider.\n // User-provided headers take precedence over defaults (spread order).\n const headers: Record<string, string> = {\n 'User-Agent': `@gleanwork/mcp-server-tester/${packageJson.version}`,\n ...validatedConfig.headers,\n };\n\n // If using client credentials grant, fetch a token first\n if (validatedConfig.auth?.clientCredentials && !options?.authProvider) {\n const ccConfig = validatedConfig.auth.clientCredentials;\n const clientId = ccConfig.clientId ?? process.env['MCP_CLIENT_ID'];\n const clientSecret =\n ccConfig.clientSecret ?? process.env['MCP_CLIENT_SECRET'];\n\n if (!clientId || !clientSecret) {\n throw new Error(\n 'Client credentials require clientId/clientSecret in config or MCP_CLIENT_ID/MCP_CLIENT_SECRET env vars'\n );\n }\n\n if (!ccConfig.tokenEndpoint) {\n throw new Error(\n 'Client credentials require tokenEndpoint in auth.clientCredentials config'\n );\n }\n\n debugClient('Fetching token via client credentials grant');\n const tokenResult = await performClientCredentialsFlow({\n tokenEndpoint: ccConfig.tokenEndpoint,\n clientId,\n clientSecret,\n scopes: ccConfig.scopes,\n });\n headers.Authorization = `Bearer ${tokenResult.accessToken}`;\n }\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 url = new URL(validatedConfig.serverUrl);\n let requestInit: RequestInit | undefined =\n Object.keys(headers).length > 0 ? { headers } : undefined;\n\n // Apply proxy if configured or available from environment\n const proxyUrl =\n validatedConfig.proxy?.url ??\n process.env['HTTPS_PROXY'] ??\n process.env['HTTP_PROXY'];\n\n if (proxyUrl) {\n const proxyAgent = new ProxyAgent(proxyUrl);\n try {\n const sanitized = new URL(proxyUrl);\n debugClient(\n 'Using proxy: %s://%s:%s',\n sanitized.protocol.slice(0, -1),\n sanitized.hostname,\n sanitized.port\n );\n } catch {\n debugClient('Using proxy (unparseable URL)');\n }\n requestInit = {\n ...requestInit,\n dispatcher: proxyAgent,\n } as unknown as RequestInit;\n }\n\n // Apply TLS configuration if present\n if (validatedConfig.tls) {\n const tlsCfg = validatedConfig.tls;\n try {\n const dispatcher = new UndiciAgent({\n connect: {\n ...(tlsCfg.ca && { ca: readFileSync(tlsCfg.ca) }),\n ...(tlsCfg.cert && { cert: readFileSync(tlsCfg.cert) }),\n ...(tlsCfg.key && { key: readFileSync(tlsCfg.key) }),\n rejectUnauthorized: tlsCfg.rejectUnauthorized ?? true,\n },\n });\n agentRegistry.set(client, dispatcher);\n requestInit = {\n ...requestInit,\n dispatcher,\n } as unknown as RequestInit;\n debugClient('TLS configuration applied');\n } catch (error) {\n const filePath = tlsCfg.ca ?? tlsCfg.cert ?? tlsCfg.key;\n const fileType = tlsCfg.ca\n ? 'CA certificate'\n : tlsCfg.cert\n ? 'client certificate'\n : 'client key';\n throw new Error(\n `Failed to load TLS ${fileType} from ${filePath}: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n } else if (proxyUrl) {\n // Track ProxyAgent for cleanup (already created above in the proxy branch)\n // Re-extract if already set via requestInit\n const existingDispatcher = (\n requestInit as unknown as { dispatcher?: ProxyAgent }\n )?.dispatcher;\n if (existingDispatcher) {\n agentRegistry.set(client, existingDispatcher);\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 debugHttp('Connecting to %s', validatedConfig.serverUrl);\n if (Object.keys(headers).length > 0) {\n debugHttp('Request header names: %O', Object.keys(headers));\n }\n\n const retryAttempts = validatedConfig.retryAttempts ?? 0;\n const connectOptions =\n validatedConfig.connectTimeoutMs !== undefined\n ? { timeout: validatedConfig.connectTimeoutMs }\n : undefined;\n\n // Try Streamable HTTP first (MCP spec 2025-03-26), fall back to SSE (2024-11-05)\n await retryWithBackoff(async () => {\n try {\n debugHttp('Attempting transport: streamableHttp');\n const streamableTransport = new StreamableHTTPClientTransport(url, {\n requestInit,\n authProvider: options?.authProvider,\n });\n await client.connect(streamableTransport, connectOptions);\n debugClient('Connected via Streamable HTTP');\n debugHttp('Connection established via streamableHttp');\n } catch (err) {\n debugHttp(\n 'streamableHttp failed (%s), falling back to SSE',\n (err as Error).message\n );\n debugClient('Streamable HTTP failed, falling back to SSE transport');\n debugHttp('Attempting transport: sse');\n const sseTransport = new SSEClientTransport(url, {\n requestInit,\n authProvider: options?.authProvider,\n });\n await client.connect(sseTransport, connectOptions);\n debugClient('Connected via SSE');\n debugHttp('Connection established via sse');\n }\n }, retryAttempts);\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 // notifications/cancelled requires a specific requestId to be useful — without one\n // the server cannot identify which request to abort. The MCP SDK does not expose\n // outstanding request IDs as a public API, so we close directly and let the\n // transport teardown signal disconnection to the server.\n try {\n await client.close();\n } catch (error) {\n debugClient(\n 'Error closing client: %s',\n error instanceof Error ? error.message : String(error)\n );\n throw error;\n } finally {\n // Close any pooled undici agent associated with this client\n const agent = agentRegistry.get(client);\n if (agent) {\n agentRegistry.delete(client);\n try {\n await agent.close();\n } catch (agentError) {\n debugClient(\n 'Error closing undici agent: %s',\n (agentError as Error).message\n );\n }\n }\n }\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\nconst DEFAULT_CALL_TIMEOUT_MS = 30_000;\n\nfunction withCallTimeout<T>(\n promise: Promise<T>,\n ms: number,\n opName: string\n): Promise<T> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n return Promise.race([\n promise,\n new Promise<never>((_, reject) => {\n timer = setTimeout(\n () =>\n reject(\n new Error(`MCP operation \"${opName}\" timed out after ${ms}ms`)\n ),\n ms\n );\n }),\n ]).finally(() => clearTimeout(timer));\n}\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 * Timeout in milliseconds for MCP tool/list operations. Default: 30000\n */\n callTimeoutMs?: number;\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, providing a high-level\n * {@link MCPFixtureApi} without requiring Playwright's `test.extend` pattern.\n *\n * Use this when you need to set up an MCP fixture manually — for example in\n * custom fixture hierarchies, non-Playwright test runners (e.g. Vitest,\n * Jest), or when you want to compose the fixture with other lifecycle\n * management logic that doesn't fit the standard `test.extend` model.\n *\n * For the typical Playwright use case, prefer importing `test` and `mcp`\n * directly from `@gleanwork/mcp-server-tester/fixtures/mcp`, which wires\n * this function up automatically.\n *\n * When `testInfo` is provided, all MCP operations are automatically wrapped\n * in `test.step()` calls and attachments are created for the MCP Test\n * Reporter. Omit `testInfo` for lightweight usage outside Playwright.\n *\n * @param client - The MCP client to wrap (created via `createMCPClientForConfig`)\n * @param testInfo - Optional Playwright TestInfo for auto-tracking and reporter attachments\n * @param options - Optional fixture options (authType, project)\n * @returns MCPFixtureApi instance\n *\n * @example\n * ```typescript\n * // Advanced: custom fixture setup inside test.extend\n * const test = base.extend<{ mcp: MCPFixtureApi }>({\n * mcp: async ({}, use, testInfo) => {\n * const client = await createMCPClientForConfig(config);\n * const api = createMCPFixture(client, testInfo, { authType: 'api-token' });\n * await use(api);\n * await closeMCPClient(client);\n * }\n * });\n *\n * // Non-Playwright usage (no reporter attachments)\n * const client = await createMCPClientForConfig(config);\n * const api = createMCPFixture(client);\n * const tools = await api.listTools();\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 const callTimeout = options?.callTimeoutMs ?? DEFAULT_CALL_TIMEOUT_MS;\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 withCallTimeout(\n client.listTools() as Promise<ListToolsResult>,\n callTimeout,\n 'listTools'\n );\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 withCallTimeout(\n client.callTool({\n name,\n arguments: args,\n }) as Promise<CallToolResult>,\n callTimeout,\n `callTool(\"${name}\")`\n );\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 withCallTimeout(\n client.listTools() as Promise<ListToolsResult>,\n callTimeout,\n 'listTools'\n );\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 withCallTimeout(\n client.callTool({\n name,\n arguments: args,\n }) as Promise<CallToolResult>,\n callTimeout,\n `callTool(\"${name}\")`\n );\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((err) => {\n console.error('[MCPFixture] Failed to attach server info:', err);\n });\n\n return result;\n },\n };\n}\n","/**\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: '@gleanwork/mcp-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 * The code verifier is cleared after a successful token exchange — it is\n * single-use per PKCE spec and must not persist beyond the exchange.\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 // Clear codeVerifier after successful token exchange — it's single-use per PKCE spec\n delete state.codeVerifier;\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, mode: 0o700 });\n\n await fs.writeFile(\n this.config.storagePath,\n JSON.stringify(state, null, 2),\n { encoding: 'utf-8', mode: 0o600 }\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-server-tester 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-server-tester 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, mode: 0o700 });\n\n await fs.writeFile(storagePath, JSON.stringify(state, null, 2), {\n encoding: 'utf-8',\n mode: 0o600,\n });\n}\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 * Returns true if the hostname refers to the loopback interface\n */\nfunction isLocalhostUrl(url: string): boolean {\n try {\n const parsed = new URL(url);\n const h = parsed.hostname;\n return h === 'localhost' || h === '127.0.0.1' || h === '::1';\n } catch {\n return false;\n }\n}\n\n/**\n * Validates that critical OAuth endpoints returned by discovery use HTTPS.\n * Localhost URLs are exempt to support local development and testing.\n *\n * @throws Error if any endpoint uses a non-HTTPS, non-localhost scheme\n */\nfunction validateAuthServerEndpoints(authServer: {\n authorization_endpoint?: string;\n token_endpoint?: string;\n issuer?: string;\n}): void {\n const endpoints = [\n { name: 'authorization_endpoint', url: authServer.authorization_endpoint },\n { name: 'token_endpoint', url: authServer.token_endpoint },\n ];\n\n for (const { name, url } of endpoints) {\n if (url && !url.startsWith('https://') && !isLocalhostUrl(url)) {\n throw new Error(\n `OAuth discovery returned an insecure ${name}: \"${url}\". ` +\n `Only HTTPS endpoints are permitted for OAuth flows to prevent token interception.`\n );\n }\n }\n}\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 validateAuthServerEndpoints(metadata);\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-server-tester 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-server-tester login https://api.example.com/mcp\n * const tokens = await loadTokens('https://api.example.com/mcp');\n * if (tokens?.accessToken) {\n * // Use the token — never log raw token values\n * headers.Authorization = `Bearer ${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-server-tester 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 // Note: The `mode` parameter is ignored on Windows (Win32) where file\n // permissions are controlled by NTFS ACLs, not Unix permission bits.\n // On Windows, token files may be readable by other users on the system\n // depending on the directory's inherited ACL. This is a Node.js fs\n // limitation. Windows users should verify %LOCALAPPDATA% permissions manually.\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 * 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-server-tester: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 = '@gleanwork/mcp-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 // Log only non-sensitive parts of the authorization URL.\n // Do NOT log: state, code_challenge, code_challenge_method (security-sensitive).\n debug(\n 'Authorization URL (base): %s',\n `${authUrl.origin}${authUrl.pathname}`\n );\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 { 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';\nimport packageJson from '../../package.json' with { type: 'json' };\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 '@gleanwork/mcp-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-server-tester 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 // Narrow to HTTP config once for all auth-related logic (auth is HTTP-only)\n const httpConfig = isHttpConfig(mcpConfig) ? mcpConfig : null;\n\n // Create auth provider if OAuth authStatePath is configured\n let authProvider: OAuthClientProvider | undefined;\n if (httpConfig?.auth?.oauth?.authStatePath) {\n authProvider = new PlaywrightOAuthClientProvider({\n storagePath: httpConfig.auth.oauth.authStatePath,\n redirectUri:\n httpConfig.auth.oauth.redirectUri ??\n 'http://localhost:3000/oauth/callback',\n clientId: httpConfig.auth.oauth.clientId,\n clientSecret: httpConfig.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 (httpConfig?.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-server-tester login <url>` then run tests\n if (\n httpConfig &&\n !httpConfig.auth?.accessToken &&\n !httpConfig.auth?.oauth?.authStatePath\n ) {\n const cliClient = new CLIOAuthClient({\n mcpServerUrl: httpConfig.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 ...httpConfig,\n auth: {\n ...httpConfig.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: '@gleanwork/mcp-server-tester',\n version: packageJson.version,\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 useConfig = testInfo.project.use as { mcpConfig?: MCPConfig };\n const api = createMCPFixture(mcpClient, testInfo, {\n authType: _mcpFixtureState.resolvedAuthType,\n project: testInfo.project.name,\n callTimeoutMs: useConfig.mcpConfig?.callTimeoutMs,\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"]}
1
+ {"version":3,"sources":["../../src/mcp/response.ts","../../src/assertions/validators/utils.ts","../../src/assertions/validators/response.ts","../../src/assertions/matchers/toMatchToolResponse.ts","../../src/assertions/validators/schema.ts","../../src/assertions/matchers/toMatchToolSchema.ts","../../src/assertions/validators/text.ts","../../src/assertions/matchers/toContainToolText.ts","../../src/assertions/validators/pattern.ts","../../src/assertions/matchers/toMatchToolPattern.ts","../../src/assertions/matchers/toMatchToolSnapshot.ts","../../src/assertions/validators/error.ts","../../src/assertions/matchers/toBeToolError.ts","../../src/judge/rubrics.ts","../../src/judge/judgeTypes.ts","../../src/judge/anthropicJudge.ts","../../src/judge/vertexAnthropicJudge.ts","../../src/judge/claudeAgentJudge.ts","../../src/judge/openaiJudge.ts","../../src/judge/googleJudge.ts","../../src/judge/judgeClient.ts","../../src/judge/judgeRegistry.ts","../../src/assertions/validators/judge.ts","../../src/assertions/matchers/toPassToolJudge.ts","../../src/assertions/validators/size.ts","../../src/assertions/matchers/toHaveToolResponseSize.ts","../../src/assertions/matchers/toSatisfyToolPredicate.ts","../../src/assertions/validators/toolCalls.ts","../../src/assertions/matchers/toHaveToolCalls.ts","../../src/assertions/matchers/toHaveToolCallCount.ts","../../src/assertions/matchers/index.ts","../../src/config/mcpConfig.ts","../../src/debug.ts","../../package.json","../../src/auth/oauthFlow.ts","../../src/mcp/clientFactory.ts","../../src/mcp/fixtures/mcpFixture.ts","../../src/auth/oauthClientProvider.ts","../../src/auth/discovery.ts","../../src/auth/storage.ts","../../src/auth/cli.ts","../../src/fixtures/mcp.ts"],"names":["extractText","truncateForDisplay","path","baseExpect","buildJudgePrompt","parseJudgeResponse","z","createDebug","UndiciAgent","fs","oauth2","debug","base"],"mappings":"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","file":"mcp.js","sourcesContent":["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 content as a direct string (single content block format)\n if (typeof r.content === 'string') {\n return 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 // Per MCP spec, content is required in CallToolResult — isError alone is insufficient\n return Array.isArray(v.content);\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/**\n * Normalizes whitespace in text for consistent comparison\n *\n * Collapses multiple whitespace characters (spaces, tabs, newlines) into single spaces\n * and trims leading/trailing whitespace.\n *\n * @param text - Text to normalize\n * @returns Normalized text with collapsed whitespace\n *\n * @example\n * ```typescript\n * normalizeWhitespace(' hello\\n\\n world ');\n * // Returns: \"hello world\"\n * ```\n */\nexport function normalizeWhitespace(text: string): string {\n return text.replace(/\\s+/g, ' ').trim();\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 * 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 * 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, stringifyResponse } 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 const text = stringifyResponse(response);\n return {\n pass: false,\n message: `Response does not match schema: ${issues}`,\n details: {\n issues: zodError.issues,\n textPreview: truncateForDisplay(text),\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\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 * 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 const preview = result.details?.textPreview as string | undefined;\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 if (!result.pass && preview) {\n return `${result.message}\\n\\nActual response (truncated):\\n${preview}`;\n }\n return result.message;\n },\n };\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 * 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 const preview = result.details?.textPreview as string | undefined;\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 if (!result.pass && preview) {\n return `${result.message}\\n\\nActual response (truncated):\\n${preview}`;\n }\n return result.message;\n },\n };\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 * 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 const preview = result.details?.textPreview as string | undefined;\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 if (!result.pass && preview) {\n return `${result.message}\\n\\nActual response (truncated):\\n${preview}`;\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 let pattern: RegExp;\n if (sanitizer.pattern instanceof RegExp) {\n pattern = sanitizer.pattern;\n } else {\n try {\n pattern = new RegExp(sanitizer.pattern, 'g');\n } catch {\n throw new Error(\n `toMatchToolSnapshot: invalid regex pattern \"${sanitizer.pattern}\" in sanitizer`\n );\n }\n }\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 * @remarks\n * **Requires Playwright test context.** This matcher calls `expect(content).toMatchSnapshot()`\n * internally, which only works inside a Playwright test (i.e., when `testInfo` is available).\n * Calling it outside a Playwright test will throw a cryptic context error.\n *\n * To test sanitizer logic without a Playwright context, use the exported `applySanitizers`\n * function directly.\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 * 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 * 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","/**\n * Built-in judge rubrics matching Glean EvalV2's named judge types.\n * Use these for consistent, standardized evaluations across teams.\n *\n * All built-in rubrics use a 5-point scale: 0.0 / 0.25 / 0.5 / 0.75 / 1.0\n */\nexport type BuiltInRubric =\n | 'correctness'\n | 'completeness'\n | 'groundedness'\n | 'instruction-following'\n | 'conciseness';\n\nexport const BUILT_IN_RUBRICS: Record<BuiltInRubric, string> = {\n correctness:\n 'Evaluate whether the response is factually correct and accurately answers the question. ' +\n 'Compare against the reference answer if provided. ' +\n 'Score 1.0 for fully correct with no errors; ' +\n 'Score 0.75 for mostly correct with one minor inaccuracy or omission; ' +\n 'Score 0.5 for partially correct — answers part of the question but misses key elements; ' +\n 'Score 0.25 for minimally relevant but substantially incorrect or missing most key details; ' +\n 'Score 0.0 for incorrect, irrelevant, or directly contradicting the reference.',\n\n completeness:\n 'Evaluate whether the response fully addresses all aspects of the question. ' +\n 'Score 1.0 if the response covers all key points comprehensively; ' +\n 'Score 0.75 if the response covers most key points with one minor gap; ' +\n 'Score 0.5 if the response partially answers — covers some aspects but misses others; ' +\n 'Score 0.25 if the response touches on the topic but misses most key aspects; ' +\n 'Score 0.0 if major aspects of the question are entirely missing or the response is off-topic.',\n\n groundedness:\n 'Evaluate whether all claims in the response are supported by the retrieved context or reference. ' +\n 'Penalize unsupported assertions or hallucinated facts. ' +\n 'Score 1.0 for fully grounded — every claim is traceable to the provided context; ' +\n 'Score 0.75 for mostly grounded with one minor unsupported detail; ' +\n 'Score 0.5 for partially grounded — some claims are supported but notable hallucinations are present; ' +\n 'Score 0.25 for minimally grounded — most claims are unsupported or invented; ' +\n 'Score 0.0 for completely hallucinated or contradicting the provided context.',\n\n 'instruction-following':\n 'Evaluate whether the response follows the instructions given in the question. ' +\n 'Check format, tone, constraints, and task completion. ' +\n 'Score 1.0 for full compliance — all instructions are followed precisely; ' +\n 'Score 0.75 for mostly compliant with one minor deviation from the instructions; ' +\n 'Score 0.5 for partial compliance — some instructions followed but key constraints violated; ' +\n 'Score 0.25 for minimal compliance — the response loosely addresses the task but ignores most instructions; ' +\n 'Score 0.0 for non-compliance — the response disregards the instructions entirely.',\n\n conciseness:\n 'Evaluate whether the response is appropriately concise without losing important information. ' +\n 'Penalize unnecessary verbosity, padding, or repetition. ' +\n 'Score 1.0 for well-sized — concise and complete with no unnecessary content; ' +\n 'Score 0.75 for slightly verbose but no information is lost or repeated; ' +\n 'Score 0.5 for moderately verbose — some padding or repetition that reduces clarity; ' +\n 'Score 0.25 for excessively verbose — significantly overlong with substantial filler or repetition; ' +\n 'Score 0.0 for extremely verbose — so padded or repetitive that the core answer is obscured.',\n};\n\n/** A rubric specification: either a built-in named rubric or custom text. */\nexport type RubricSpec = BuiltInRubric | { text: string };\n\n/**\n * Returns true if `s` is a built-in rubric name.\n */\nexport function isBuiltInRubric(s: unknown): s is BuiltInRubric {\n return typeof s === 'string' && s in BUILT_IN_RUBRICS;\n}\n\n/**\n * Resolves a RubricSpec to its full rubric text.\n * - Built-in name → returns the expanded rubric text from BUILT_IN_RUBRICS\n * - Custom object → returns rubric.text as-is\n */\nexport function resolveRubric(rubric: RubricSpec): string {\n if (typeof rubric === 'string') {\n return BUILT_IN_RUBRICS[rubric];\n }\n return rubric.text;\n}\n","import { z } from 'zod';\n\n/**\n * Zod schema for validating judge LLM responses.\n * Ensures the response has the required structure before it is used.\n */\nexport const JudgeResponseSchema = z.object({\n pass: z.boolean(),\n score: z.number().min(0).max(1),\n reasoning: z.string(),\n});\n\n/**\n * The validated shape returned by a judge LLM.\n */\nexport type JudgeResponse = z.infer<typeof JudgeResponseSchema>;\n\n/**\n * Usage metrics from Claude Agent SDK response\n */\nexport interface UsageMetrics {\n /**\n * Number of input tokens consumed\n */\n inputTokens: number;\n\n /**\n * Number of output tokens generated\n */\n outputTokens: number;\n\n /**\n * Total cost in USD\n */\n totalCostUsd: number;\n\n /**\n * Execution duration in milliseconds\n */\n durationMs: number;\n\n /**\n * API call duration in milliseconds (excluding network overhead)\n */\n durationApiMs?: number;\n\n /**\n * Number of tokens read from cache\n */\n cacheReadInputTokens?: number;\n\n /**\n * Number of tokens written to cache\n */\n cacheCreationInputTokens?: number;\n}\n\n/** Valid LLM judge provider kinds. */\nexport type ProviderKind =\n | 'anthropic'\n | 'vertex-anthropic'\n | 'anthropic-agent-sdk'\n | 'openai'\n | 'google';\n\n/**\n * Configuration for an LLM judge\n */\nexport interface JudgeConfig {\n /**\n * LLM provider to use\n * @default 'anthropic'\n */\n provider?: ProviderKind;\n\n /**\n * Environment variable name containing the API key\n * @default 'ANTHROPIC_API_KEY'\n */\n apiKeyEnvVar?: string;\n\n /**\n * Model to use for judging\n * @default 'claude-sonnet-4-20250514'\n */\n model?: string;\n\n /**\n * Maximum tokens for response\n * @default 1000\n */\n maxTokens?: number;\n\n /**\n * Temperature (0-1, lower is more deterministic)\n * @default 0.0\n */\n temperature?: number;\n\n /**\n * Maximum budget in USD for the judge evaluation\n * @default 0.10\n */\n maxBudgetUsd?: number;\n\n /**\n * Maximum size (in bytes) for tool output before failing the test\n * When set, the judge will fail if the candidate response exceeds this size\n */\n maxToolOutputSize?: number;\n}\n\n/**\n * Result from LLM judge evaluation\n */\nexport interface JudgeResult {\n /**\n * Whether the evaluation passed\n */\n pass: boolean;\n\n /**\n * Numeric score (0-1, where 1 is best)\n */\n score?: number;\n\n /**\n * Reasoning/explanation from the judge\n */\n reasoning?: string;\n\n /**\n * Usage metrics from the Claude Agent SDK\n */\n usage?: UsageMetrics;\n\n /**\n * Size of the candidate response in bytes (for maxToolOutputSize tracking)\n */\n candidateSizeBytes?: number;\n\n /**\n * Whether the candidate exceeded maxToolOutputSize\n */\n exceedsMaxToolOutputSize?: boolean;\n\n /**\n * Standard deviation of individual rep scores.\n * Only populated when the judge was run with reps > 1.\n */\n scoreStdDev?: number;\n\n /**\n * True when the standard deviation across reps exceeds 0.2, indicating\n * that the rubric may be ambiguous or the judge is non-deterministic.\n * Only populated when the judge was run with reps > 1.\n */\n highVariance?: boolean;\n\n /**\n * Individual scores from each judge rep.\n * Only populated when the judge was run with reps > 1.\n */\n scores?: number[];\n}\n\nexport type { BuiltInRubric, RubricSpec } from './rubrics.js';\nexport { BUILT_IN_RUBRICS, resolveRubric, isBuiltInRubric } from './rubrics.js';\n\n/**\n * LLM judge client interface\n */\nexport interface Judge {\n /**\n * Evaluates a candidate response against a reference\n *\n * @param candidate - The actual response to evaluate\n * @param reference - The expected/reference response (or null if not applicable)\n * @param rubric - The evaluation rubric/criteria\n * @returns Evaluation result with usage metrics\n */\n evaluate(\n candidate: unknown,\n reference: unknown,\n rubric: string\n ): Promise<JudgeResult>;\n}\n","/* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any */\nimport type { Judge, JudgeConfig, JudgeResult } from './judgeTypes.js';\nimport { JudgeResponseSchema } from './judgeTypes.js';\n\n/**\n * Creates an Anthropic-backed LLM judge using the Anthropic SDK directly.\n * Requires the `@anthropic-ai/sdk` package and an Anthropic API key.\n */\nexport function createAnthropicJudge(config: JudgeConfig = {}): Judge {\n const apiKeyEnvVar = config.apiKeyEnvVar ?? 'ANTHROPIC_API_KEY';\n const apiKey = process.env[apiKeyEnvVar];\n if (!apiKey) {\n throw new Error(\n `Anthropic judge requires an API key. Set the ${apiKeyEnvVar} environment variable.`\n );\n }\n\n const model = config.model ?? 'claude-sonnet-4-20250514';\n const maxTokens = config.maxTokens ?? 1000;\n const temperature = config.temperature ?? 0.0;\n\n return {\n async evaluate(candidate, reference, rubric): Promise<JudgeResult> {\n let anthropicModule: any;\n try {\n // @ts-expect-error - optional: npm install @anthropic-ai/sdk\n anthropicModule = await import('@anthropic-ai/sdk');\n } catch (err) {\n throw new Error(\n 'Anthropic judge requires the `@anthropic-ai/sdk` package. ' +\n 'Install it with: npm install @anthropic-ai/sdk\\n' +\n `Original error: ${err instanceof Error ? err.message : String(err)}`\n );\n }\n\n const client = new anthropicModule.default({ apiKey });\n const prompt = buildJudgePrompt(candidate, reference, rubric);\n\n const startTime = Date.now();\n const response = await client.messages.create({\n model,\n max_tokens: maxTokens,\n temperature,\n system:\n 'You are an expert evaluator. Respond with valid JSON only: {\"pass\": true|false, \"score\": 0.0-1.0, \"reasoning\": \"explanation\"}',\n messages: [{ role: 'user', content: prompt }],\n });\n const durationMs = Date.now() - startTime;\n\n const textBlock = (response.content as any[]).find(\n (b: any) => b.type === 'text'\n );\n const text = (textBlock?.text as string) ?? '';\n const parsed = parseJudgeResponse(text);\n\n return {\n pass: parsed.pass,\n score: parsed.score,\n reasoning: parsed.reasoning,\n usage: {\n inputTokens: (response.usage?.input_tokens as number) ?? 0,\n outputTokens: (response.usage?.output_tokens as number) ?? 0,\n totalCostUsd: 0,\n durationMs,\n },\n };\n },\n };\n}\n\nfunction buildJudgePrompt(\n candidate: unknown,\n reference: unknown,\n rubric: string\n): string {\n const candidateStr =\n typeof candidate === 'string'\n ? candidate\n : JSON.stringify(candidate, null, 2);\n\n const referenceStr =\n reference !== null && reference !== undefined\n ? typeof reference === 'string'\n ? reference\n : JSON.stringify(reference, null, 2)\n : null;\n\n return (\n `Rubric:\\n${rubric}\\n\\n` +\n `<candidate_response>\\n${candidateStr}\\n</candidate_response>\\n\\n` +\n `<reference_answer>\\n${referenceStr ?? 'No reference provided.'}\\n</reference_answer>\\n\\n` +\n `Evaluate and return JSON: {\"pass\": boolean, \"score\": number (0-1), \"reasoning\": string}`\n );\n}\n\nfunction parseJudgeResponse(text: string): {\n pass: boolean;\n score: number;\n reasoning: string;\n} {\n const cleaned = text\n .replace(/```json\\n?/g, '')\n .replace(/```\\n?/g, '')\n .trim();\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(cleaned);\n } catch {\n throw new Error(`Failed to parse judge response as JSON: ${text}`);\n }\n\n const result = JudgeResponseSchema.safeParse(parsed);\n if (!result.success) {\n throw new Error(\n `Judge returned invalid response. Expected {pass, score, reasoning} but got: ${cleaned.slice(0, 500)}\\nValidation errors: ${JSON.stringify(result.error.issues)}`\n );\n }\n return result.data;\n}\n","/* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any */\nimport type { Judge, JudgeConfig, JudgeResult } from './judgeTypes.js';\nimport { JudgeResponseSchema } from './judgeTypes.js';\n\n/**\n * Creates an Anthropic-backed LLM judge that routes through Google Vertex AI.\n * Requires the `@anthropic-ai/vertex-sdk` package and Application Default Credentials.\n * Set GOOGLE_VERTEX_PROJECT and GOOGLE_VERTEX_LOCATION env vars.\n */\nexport function createVertexAnthropicJudge(config: JudgeConfig = {}): Judge {\n const model = config.model ?? 'claude-sonnet-4-20250514';\n const maxTokens = config.maxTokens ?? 1000;\n const temperature = config.temperature ?? 0.0;\n\n return {\n async evaluate(candidate, reference, rubric): Promise<JudgeResult> {\n let vertexModule: any;\n try {\n // @ts-expect-error - optional: npm install @anthropic-ai/vertex-sdk\n vertexModule = await import('@anthropic-ai/vertex-sdk');\n } catch (err) {\n throw new Error(\n 'Vertex Anthropic judge requires the `@anthropic-ai/vertex-sdk` package. ' +\n 'Install it with: npm install @anthropic-ai/vertex-sdk\\n' +\n `Original error: ${err instanceof Error ? err.message : String(err)}`\n );\n }\n\n const client = new vertexModule.AnthropicVertex({\n projectId:\n process.env.GOOGLE_VERTEX_PROJECT ?? process.env.CLOUD_ML_PROJECT_ID,\n region: process.env.GOOGLE_VERTEX_LOCATION ?? 'us-east5',\n });\n\n const prompt = buildJudgePrompt(candidate, reference, rubric);\n\n const startTime = Date.now();\n const response = await client.messages.create({\n model,\n max_tokens: maxTokens,\n temperature,\n system:\n 'You are an expert evaluator. Respond with valid JSON only: {\"pass\": true|false, \"score\": 0.0-1.0, \"reasoning\": \"explanation\"}',\n messages: [{ role: 'user', content: prompt }],\n });\n const durationMs = Date.now() - startTime;\n\n const textBlock = (response.content as any[]).find(\n (b: any) => b.type === 'text'\n );\n const text = (textBlock?.text as string) ?? '';\n const parsed = parseJudgeResponse(text);\n\n return {\n pass: parsed.pass,\n score: parsed.score,\n reasoning: parsed.reasoning,\n usage: {\n inputTokens: (response.usage?.input_tokens as number) ?? 0,\n outputTokens: (response.usage?.output_tokens as number) ?? 0,\n totalCostUsd: 0,\n durationMs,\n },\n };\n },\n };\n}\n\nfunction buildJudgePrompt(\n candidate: unknown,\n reference: unknown,\n rubric: string\n): string {\n const candidateStr =\n typeof candidate === 'string'\n ? candidate\n : JSON.stringify(candidate, null, 2);\n\n const referenceStr =\n reference !== null && reference !== undefined\n ? typeof reference === 'string'\n ? reference\n : JSON.stringify(reference, null, 2)\n : null;\n\n return (\n `Rubric:\\n${rubric}\\n\\n` +\n `<candidate_response>\\n${candidateStr}\\n</candidate_response>\\n\\n` +\n `<reference_answer>\\n${referenceStr ?? 'No reference provided.'}\\n</reference_answer>\\n\\n` +\n `Evaluate and return JSON: {\"pass\": boolean, \"score\": number (0-1), \"reasoning\": string}`\n );\n}\n\nfunction parseJudgeResponse(text: string): {\n pass: boolean;\n score: number;\n reasoning: string;\n} {\n const cleaned = text\n .replace(/```json\\n?/g, '')\n .replace(/```\\n?/g, '')\n .trim();\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(cleaned);\n } catch {\n throw new Error(`Failed to parse judge response as JSON: ${text}`);\n }\n\n const result = JudgeResponseSchema.safeParse(parsed);\n if (!result.success) {\n throw new Error(\n `Judge returned invalid response. Expected {pass, score, reasoning} but got: ${cleaned.slice(0, 500)}\\nValidation errors: ${JSON.stringify(result.error.issues)}`\n );\n }\n return result.data;\n}\n","import { query } from '@anthropic-ai/claude-agent-sdk';\nimport type {\n JudgeConfig,\n Judge,\n JudgeResult,\n UsageMetrics,\n} from './judgeTypes.js';\nimport { JudgeResponseSchema } 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,\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 candidateStr =\n typeof candidate === 'string'\n ? candidate\n : JSON.stringify(candidate, null, 2);\n\n const referenceStr =\n reference !== null && reference !== undefined\n ? typeof reference === 'string'\n ? reference\n : JSON.stringify(reference, null, 2)\n : null;\n\n const parts: Array<string> = [];\n\n parts.push('Rubric:\\n');\n parts.push(rubric);\n parts.push('\\n\\n<candidate_response>\\n');\n parts.push(candidateStr);\n parts.push('\\n</candidate_response>\\n\\n');\n\n parts.push('<reference_answer>\\n');\n parts.push(referenceStr ?? 'No reference provided.');\n parts.push('\\n</reference_answer>\\n\\n');\n\n parts.push(\n 'Evaluate the candidate response against the rubric' +\n (referenceStr !== null\n ? ', comparing it with the reference answer if helpful'\n : '') +\n '. Return JSON: {\"pass\": boolean, \"score\": number (0-1), \"reasoning\": string}'\n );\n\n return parts.join('');\n}\n\n/**\n * Parses and validates the JSON response from the judge, handling markdown code blocks.\n * Throws a descriptive error if the response cannot be parsed or fails schema validation.\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 let parsed: unknown;\n try {\n parsed = JSON.parse(jsonText);\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 parsed = JSON.parse(jsonMatch[0]);\n } else {\n throw new Error(`Failed to parse judge response as JSON: ${text}`);\n }\n }\n\n const result = JudgeResponseSchema.safeParse(parsed);\n if (!result.success) {\n throw new Error(\n `Judge returned invalid response. Expected {pass, score, reasoning} but got: ${jsonText.slice(0, 500)}\\nValidation errors: ${JSON.stringify(result.error.issues)}`\n );\n }\n return result.data;\n}\n","/* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any */\nimport type { Judge, JudgeConfig, JudgeResult } from './judgeTypes.js';\nimport { JudgeResponseSchema } from './judgeTypes.js';\n\n/**\n * Creates an OpenAI-backed LLM judge.\n * Requires the `openai` package and an OpenAI API key.\n */\nexport function createOpenAIJudge(config: JudgeConfig = {}): Judge {\n const apiKeyEnvVar = config.apiKeyEnvVar ?? 'OPENAI_API_KEY';\n const apiKey = process.env[apiKeyEnvVar];\n if (!apiKey) {\n throw new Error(\n `OpenAI judge requires an API key. Set the ${apiKeyEnvVar} environment variable.`\n );\n }\n\n const model = config.model ?? 'gpt-4o';\n const maxTokens = config.maxTokens ?? 1000;\n const temperature = config.temperature ?? 0.0;\n\n return {\n async evaluate(candidate, reference, rubric): Promise<JudgeResult> {\n // Dynamic import keeps `openai` an optional runtime dep.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let openaiModule: any;\n try {\n // @ts-expect-error - optional: npm install openai\n openaiModule = await import('openai');\n } catch (err) {\n throw new Error(\n 'OpenAI judge requires the `openai` package. Install it with: npm install openai\\n' +\n `Original error: ${err instanceof Error ? err.message : String(err)}`\n );\n }\n\n const client = new openaiModule.default({ apiKey });\n const prompt = buildJudgePrompt(candidate, reference, rubric);\n\n const startTime = Date.now();\n const completion = await client.chat.completions.create({\n model,\n max_tokens: maxTokens,\n temperature,\n messages: [\n {\n role: 'system',\n content:\n 'You are an expert evaluator. Respond with valid JSON only: {\"pass\": true|false, \"score\": 0.0-1.0, \"reasoning\": \"explanation\"}',\n },\n { role: 'user', content: prompt },\n ],\n });\n const durationMs = Date.now() - startTime;\n\n const text =\n (completion.choices[0]?.message.content as string | null | undefined) ??\n '';\n const parsed = parseJudgeResponse(text);\n\n return {\n pass: parsed.pass,\n score: parsed.score,\n reasoning: parsed.reasoning,\n usage: {\n inputTokens:\n (completion.usage?.prompt_tokens as number | undefined) ?? 0,\n outputTokens:\n (completion.usage?.completion_tokens as number | undefined) ?? 0,\n totalCostUsd: 0,\n durationMs,\n },\n };\n },\n };\n}\n\nfunction buildJudgePrompt(\n candidate: unknown,\n reference: unknown,\n rubric: string\n): string {\n const candidateStr =\n typeof candidate === 'string'\n ? candidate\n : JSON.stringify(candidate, null, 2);\n\n const referenceStr =\n reference !== null && reference !== undefined\n ? typeof reference === 'string'\n ? reference\n : JSON.stringify(reference, null, 2)\n : null;\n\n return (\n `Rubric:\\n${rubric}\\n\\n` +\n `<candidate_response>\\n${candidateStr}\\n</candidate_response>\\n\\n` +\n `<reference_answer>\\n${referenceStr ?? 'No reference provided.'}\\n</reference_answer>\\n\\n` +\n `Evaluate and return JSON: {\"pass\": boolean, \"score\": number (0-1), \"reasoning\": string}`\n );\n}\n\nfunction parseJudgeResponse(text: string): {\n pass: boolean;\n score: number;\n reasoning: string;\n} {\n const cleaned = text\n .replace(/```json\\n?/g, '')\n .replace(/```\\n?/g, '')\n .trim();\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(cleaned);\n } catch {\n throw new Error(`Failed to parse judge response as JSON: ${text}`);\n }\n\n const result = JudgeResponseSchema.safeParse(parsed);\n if (!result.success) {\n throw new Error(\n `Judge returned invalid response. Expected {pass, score, reasoning} but got: ${cleaned.slice(0, 500)}\\nValidation errors: ${JSON.stringify(result.error.issues)}`\n );\n }\n return result.data;\n}\n","/* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any */\nimport type { Judge, JudgeConfig, JudgeResult } from './judgeTypes.js';\nimport { JudgeResponseSchema } from './judgeTypes.js';\n\n/**\n * Creates a Google Gemini-backed LLM judge.\n * Requires the `@google/generative-ai` package and a Google API key.\n */\nexport function createGoogleJudge(config: JudgeConfig = {}): Judge {\n const apiKeyEnvVar = config.apiKeyEnvVar ?? 'GOOGLE_API_KEY';\n const apiKey = process.env[apiKeyEnvVar];\n if (!apiKey) {\n throw new Error(\n `Google judge requires an API key. Set the ${apiKeyEnvVar} environment variable.`\n );\n }\n\n const model = config.model ?? 'gemini-2.0-flash';\n const maxTokens = config.maxTokens ?? 1000;\n\n return {\n async evaluate(candidate, reference, rubric): Promise<JudgeResult> {\n // Dynamic import keeps `@google/generative-ai` an optional runtime dep.\n let googleModule: any;\n try {\n // @ts-expect-error - optional: npm install @google/generative-ai\n googleModule = await import('@google/generative-ai');\n } catch (err) {\n throw new Error(\n 'Google judge requires the `@google/generative-ai` package. Install it with: npm install @google/generative-ai\\n' +\n `Original error: ${err instanceof Error ? err.message : String(err)}`\n );\n }\n\n const genAI = new googleModule.GoogleGenerativeAI(apiKey);\n const gemini = genAI.getGenerativeModel({\n model,\n generationConfig: {\n maxOutputTokens: maxTokens,\n temperature: 0.0,\n },\n systemInstruction:\n 'You are an expert evaluator. Respond with valid JSON only: {\"pass\": true|false, \"score\": 0.0-1.0, \"reasoning\": \"explanation\"}',\n });\n\n const candidateStr =\n typeof candidate === 'string'\n ? candidate\n : JSON.stringify(candidate, null, 2);\n\n const referenceStr =\n reference !== null && reference !== undefined\n ? typeof reference === 'string'\n ? reference\n : JSON.stringify(reference, null, 2)\n : null;\n\n const prompt =\n `Rubric:\\n${rubric}\\n\\n` +\n `<candidate_response>\\n${candidateStr}\\n</candidate_response>\\n\\n` +\n `<reference_answer>\\n${referenceStr ?? 'No reference provided.'}\\n</reference_answer>\\n\\n` +\n `Evaluate and return JSON: {\"pass\": boolean, \"score\": number (0-1), \"reasoning\": string}`;\n\n const startTime = Date.now();\n const result = await gemini.generateContent(prompt);\n const durationMs = Date.now() - startTime;\n\n const text = result.response.text() as string;\n const cleaned = text\n .replace(/```json\\n?/g, '')\n .replace(/```\\n?/g, '')\n .trim();\n\n let parsedRaw: unknown;\n try {\n parsedRaw = JSON.parse(cleaned);\n } catch {\n throw new Error(`Failed to parse judge response as JSON: ${text}`);\n }\n\n const validation = JudgeResponseSchema.safeParse(parsedRaw);\n if (!validation.success) {\n throw new Error(\n `Judge returned invalid response. Expected {pass, score, reasoning} but got: ${cleaned.slice(0, 500)}\\nValidation errors: ${JSON.stringify(validation.error.issues)}`\n );\n }\n const { pass, score, reasoning } = validation.data;\n\n return {\n pass,\n score,\n reasoning,\n usage: {\n inputTokens:\n (result.response.usageMetadata?.promptTokenCount as\n | number\n | undefined) ?? 0,\n outputTokens:\n (result.response.usageMetadata?.candidatesTokenCount as\n | number\n | undefined) ?? 0,\n totalCostUsd: 0,\n durationMs,\n },\n };\n },\n };\n}\n","import type { Judge, JudgeConfig, ProviderKind } from './judgeTypes.js';\nimport { createAnthropicJudge } from './anthropicJudge.js';\nimport { createVertexAnthropicJudge } from './vertexAnthropicJudge.js';\nimport { createClaudeAgentJudge } from './claudeAgentJudge.js';\nimport { createOpenAIJudge } from './openaiJudge.js';\nimport { createGoogleJudge } from './googleJudge.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 ?? 'anthropic';\n\n switch (provider) {\n case 'anthropic':\n return createAnthropicJudge(config);\n\n case 'vertex-anthropic':\n return createVertexAnthropicJudge(config);\n\n case 'anthropic-agent-sdk':\n return createClaudeAgentJudge(config);\n\n case 'openai':\n return createOpenAIJudge(config);\n\n case 'google':\n return createGoogleJudge(config);\n\n default:\n throw new Error(\n `Unsupported LLM provider: ${String(provider)}. Valid providers: 'anthropic', 'vertex-anthropic', 'anthropic-agent-sdk', 'openai', 'google'`\n );\n }\n}\n","/**\n * Custom Judge Registry\n *\n * Allows consumers to register named judge executors that can be referenced\n * by string ID in eval fixtures and programmatic tests. This enables\n * multi-step judge pipelines (LLM call + post-processing), custom scoring\n * logic, and reusable judge configurations without duplicating rubrics.\n */\n\n/**\n * Result returned by a custom judge executor.\n *\n * Custom judges must return a normalized score (0–1). The framework applies\n * the caller's `threshold` (default 0.7) to determine pass/fail. This keeps\n * judges reusable — the same judge can be used with different thresholds in\n * different tests.\n */\nexport interface CustomJudgeResult {\n /** Normalized score (0–1, where 1 is best) */\n score: number;\n /** Optional reasoning/explanation */\n reasoning?: string;\n}\n\n/**\n * A user-defined judge executor function.\n *\n * Custom executors own their entire evaluation pipeline — prompt construction,\n * LLM calls, and post-processing — but return a normalized score. The framework\n * determines pass/fail by comparing the score against the caller's threshold.\n *\n * @param candidate - The actual response to evaluate\n * @param reference - Optional reference/expected response\n * @returns Evaluation result with a normalized score and optional reasoning\n *\n * @example\n * ```typescript\n * const completenessJudge: CustomJudgeExecutor = async (candidate, reference) => {\n * // Step 1: LLM call with your own prompt and schema\n * const llmResult = await callLLM(COMPLETENESS_PROMPT, candidate);\n * const { verdict, reasoning } = JSON.parse(llmResult);\n *\n * // Step 2: Deterministic post-processing into a normalized score\n * const score = { Complete: 1.0, Incomplete: 0.5 }[verdict] ?? 0.0;\n *\n * return { score, reasoning };\n * };\n * ```\n */\nexport type CustomJudgeExecutor = (\n candidate: unknown,\n reference?: unknown\n) => Promise<CustomJudgeResult>;\n\nconst registry = new Map<string, CustomJudgeExecutor>();\n\n/**\n * Registers a named custom judge executor.\n *\n * Call this in your test setup (e.g., `playwright.config.ts` or a global setup file)\n * before tests run. The name can then be referenced in JSON eval fixtures via the\n * `judge` field on `passesJudge`.\n *\n * @param name - Unique identifier for the judge\n * @param executor - The judge executor function\n * @throws {Error} If a judge with the same name is already registered\n *\n * @example\n * ```typescript\n * import { registerJudge } from '@gleanwork/mcp-server-tester';\n *\n * registerJudge('glean-completeness', async (candidate, reference) => {\n * // Step 1: LLM call with your own prompt and schema\n * const llmResult = await callLLM(COMPLETENESS_PROMPT, candidate);\n * const { verdict, reasoning } = JSON.parse(llmResult);\n *\n * // Step 2: Deterministic post-processing into a normalized score\n * const score = { Complete: 1.0, Incomplete: 0.5 }[verdict] ?? 0.0;\n *\n * return { score, reasoning };\n * });\n *\n * // Then in tests — same judge, different thresholds:\n * // expect(result).toPassToolJudge({ judge: 'glean-completeness', passingThreshold: 0.8 });\n * // expect(result).toPassToolJudge({ judge: 'glean-completeness', passingThreshold: 0.5 });\n * ```\n */\nexport function registerJudge(\n name: string,\n executor: CustomJudgeExecutor\n): void {\n const existing = registry.get(name);\n if (existing !== undefined) {\n if (existing === executor) {\n return; // same function re-registered (e.g., shared setup imported by multiple files)\n }\n throw new Error(\n `Judge \"${name}\" is already registered with a different executor. ` +\n `Use clearJudgeRegistry() first if you need to replace it.`\n );\n }\n registry.set(name, executor);\n}\n\n/**\n * Retrieves a registered custom judge executor by name.\n *\n * @param name - The judge name to look up\n * @returns The registered executor\n * @throws {Error} If no judge with the given name is registered\n */\nexport function getRegisteredJudge(name: string): CustomJudgeExecutor {\n const executor = registry.get(name);\n if (!executor) {\n const available =\n registry.size > 0\n ? ` Available judges: ${[...registry.keys()].join(', ')}`\n : ' No judges are registered.';\n throw new Error(\n `Judge \"${name}\" is not registered.${available} ` +\n `Register it with registerJudge() before tests run.`\n );\n }\n return executor;\n}\n\n/**\n * Clears all registered judges. Intended for test teardown.\n */\nexport function clearJudgeRegistry(): void {\n registry.clear();\n}\n","/**\n * Judge Validator\n *\n * Validates a response using an LLM-as-a-judge evaluation.\n */\n\nimport type { ValidationResult } from './types.js';\nimport type { ProviderKind } from '../../judge/judgeTypes.js';\nimport type { RubricSpec } from '../../judge/rubrics.js';\nimport { createJudge } from '../../judge/judgeClient.js';\nimport { resolveRubric } from '../../judge/rubrics.js';\nimport { getRegisteredJudge } from '../../judge/judgeRegistry.js';\n\n/**\n * Configuration for the judge validator\n */\nexport interface JudgeValidatorConfig {\n /**\n * The evaluation rubric: a built-in name or custom { text: string }.\n * Required when no named `judge` is specified.\n */\n rubric?: RubricSpec;\n /** Optional reference response to compare against */\n reference?: unknown;\n /** Minimum score required to pass (0-1, default: 0.7) */\n threshold?: number;\n /** Number of judge evaluations to run. Scores averaged. @default 1 */\n reps?: number;\n /** Judge provider. @default 'claude' */\n provider?: ProviderKind;\n /** Model override (e.g., 'claude-opus-4-20250514') */\n model?: string;\n /** Environment variable name for API key */\n apiKeyEnvVar?: string;\n /** Max tokens for judge response */\n maxTokens?: number;\n /** Temperature for judge LLM (0–1) */\n temperature?: number;\n /** Max budget in USD per evaluation */\n maxBudgetUsd?: number;\n /** Fail if response exceeds this size in bytes before judging */\n maxToolOutputSize?: number;\n /**\n * Name of a registered custom judge executor.\n * When set, the named judge handles the entire evaluation pipeline\n * and returns a normalized score. The `threshold` determines pass/fail.\n * Register judges with `registerJudge()` before tests run.\n */\n judge?: string;\n}\n\n/**\n * Validates a response using an LLM-as-a-judge evaluation\n *\n * Calls the configured judge with the response and rubric, then checks whether\n * the resulting score meets the threshold. Returns a ValidationResult compatible\n * with the unified assertion architecture.\n *\n * @param response - The response to evaluate\n * @param config - Judge evaluation configuration (rubric, reference, threshold, provider, model, etc.)\n * @returns Validation result indicating pass/fail with judge reasoning\n *\n * @example\n * ```typescript\n * const result = await validateJudge(\n * response,\n * { rubric: 'Does the response accurately describe the weather?' }\n * );\n * if (!result.pass) {\n * console.log(result.message);\n * }\n *\n * // With inline judge config and threshold\n * const result2 = await validateJudge(\n * response,\n * { rubric: 'Is this helpful?', threshold: 0.9, model: 'claude-opus-4-20250514', temperature: 0 }\n * );\n * ```\n */\n/**\n * Computes population standard deviation of an array of scores.\n * Returns 0 when there are fewer than 2 values.\n */\nfunction computeStdDev(scores: number[], mean: number): number {\n if (scores.length <= 1) return 0;\n const variance =\n scores.reduce((sum, s) => sum + (s - mean) ** 2, 0) / scores.length;\n return Math.sqrt(variance);\n}\n\nexport async function validateJudge(\n response: unknown,\n config: JudgeValidatorConfig\n): Promise<ValidationResult> {\n const {\n judge: judgeName,\n rubric,\n reference,\n threshold = 0.7,\n reps = 1,\n provider,\n model,\n apiKeyEnvVar,\n maxTokens,\n temperature,\n maxBudgetUsd,\n maxToolOutputSize,\n } = config;\n\n // Named custom judge — executor returns a score, threshold determines pass/fail\n if (judgeName !== undefined) {\n try {\n const executor = getRegisteredJudge(judgeName);\n const judgeResult = await executor(response, reference ?? undefined);\n\n const score = judgeResult.score;\n const passed = score >= threshold;\n\n return {\n pass: passed,\n message: passed\n ? `Custom judge \"${judgeName}\" passed with score ${score.toFixed(2)}`\n : `Custom judge \"${judgeName}\" failed with score ${score.toFixed(2)} (threshold: ${threshold}). ${judgeResult.reasoning ?? ''}`,\n };\n } catch (err) {\n return {\n pass: false,\n message: `Custom judge \"${judgeName}\" error: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n }\n\n // Built-in LLM judge — requires rubric\n if (rubric === undefined) {\n return {\n pass: false,\n message:\n 'Judge evaluation failed: either \"judge\" or \"rubric\" must be provided',\n };\n }\n\n const resolvedRubric = resolveRubric(rubric);\n\n const judgeConfig = {\n ...(provider !== undefined && { provider }),\n ...(model !== undefined && { model }),\n ...(apiKeyEnvVar !== undefined && { apiKeyEnvVar }),\n ...(maxTokens !== undefined && { maxTokens }),\n ...(temperature !== undefined && { temperature }),\n ...(maxBudgetUsd !== undefined && { maxBudgetUsd }),\n ...(maxToolOutputSize !== undefined && { maxToolOutputSize }),\n };\n\n try {\n const judge = createJudge(judgeConfig);\n\n const scores: number[] = [];\n let lastReasoning: string | undefined;\n\n for (let i = 0; i < reps; i++) {\n const judgeResult = await judge.evaluate(\n response,\n reference ?? null,\n resolvedRubric\n );\n scores.push(judgeResult.score ?? (judgeResult.pass ? 1.0 : 0.0));\n lastReasoning = judgeResult.reasoning;\n }\n\n if (scores.length === 0) {\n return {\n pass: false,\n message: 'Judge evaluation failed: no scores collected',\n };\n }\n\n const meanScore = scores.reduce((a, b) => a + b, 0) / scores.length;\n const passed = meanScore >= threshold;\n const repNote =\n reps > 1\n ? ` (mean of ${reps} reps: [${scores.map((s) => s.toFixed(2)).join(', ')}])`\n : '';\n\n let stdDev: number | undefined;\n let highVariance: boolean | undefined;\n\n if (reps > 1) {\n stdDev = computeStdDev(scores, meanScore);\n highVariance = stdDev > 0.2;\n\n if (highVariance) {\n console.warn(\n `[mcp-server-tester] Judge scores have high variance ` +\n `(stdDev=${stdDev.toFixed(2)}, scores=[${scores.map((s) => s.toFixed(2)).join(', ')}]). ` +\n `The rubric may be ambiguous.`\n );\n }\n }\n\n return {\n pass: passed,\n message: passed\n ? `Judge passed with score ${meanScore.toFixed(2)}${repNote}`\n : `Judge failed with score ${meanScore.toFixed(2)} (threshold: ${threshold})${repNote}. ${lastReasoning ?? ''}`,\n details: {\n score: meanScore,\n reasoning: lastReasoning,\n judgeProvider: provider ?? 'anthropic',\n judgeModel: model,\n ...(reps > 1 && {\n scores,\n scoreStdDev: stdDev,\n highVariance,\n }),\n },\n };\n } catch (err) {\n return {\n pass: false,\n message: `Judge evaluation error: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n}\n","/**\n * toPassToolJudge Matcher\n *\n * Validates that a response passes LLM-as-judge evaluation.\n * Delegates evaluation logic to validateJudge() for consistency\n * with the validator/matcher duality pattern.\n *\n * Supports three call signatures:\n * - toPassToolJudge(rubric, options?) — built-in LLM judge with rubric\n * - toPassToolJudge({ judge: 'name', ... }) — named custom judge\n * - toPassToolJudge([...judges]) — multi-judge (all must pass)\n */\n\nimport { validateJudge } from '../validators/judge.js';\nimport type { RubricSpec } from '../../judge/rubrics.js';\nimport type { JudgeMatcherOptions } from './types.js';\n\n// Default passing threshold\nconst DEFAULT_PASSING_THRESHOLD = 0.7;\n\n/**\n * Runs a single judge evaluation and returns the result.\n */\nasync function runSingleJudge(\n received: unknown,\n rubric: RubricSpec | undefined,\n options: JudgeMatcherOptions\n): Promise<{ pass: boolean; message: string }> {\n const {\n reference = null,\n passingThreshold = DEFAULT_PASSING_THRESHOLD,\n reps,\n provider,\n model,\n judge,\n } = options;\n\n const validation = await validateJudge(received, {\n ...(rubric !== undefined && { rubric }),\n reference: reference ?? undefined,\n threshold: passingThreshold,\n ...(reps !== undefined && { reps }),\n ...(provider !== undefined && { provider }),\n ...(model !== undefined && { model }),\n ...(judge !== undefined && { judge }),\n });\n\n return { pass: validation.pass, message: validation.message };\n}\n\n/**\n * The toPassToolJudge matcher function.\n *\n * Accepts either:\n * (received, rubric, options?) — rubric-based LLM judge\n * (received, options) — named custom judge (options.judge required)\n * (received, judges[]) — multi-judge (all must pass)\n */\nexport async function toPassToolJudge(\n this: { isNot: boolean },\n received: unknown,\n rubricOrOptions:\n | RubricSpec\n | JudgeMatcherOptions\n | Array<JudgeMatcherOptions & { rubric?: RubricSpec }>,\n maybeOptions?: JudgeMatcherOptions\n): Promise<{ pass: boolean; message: () => string }> {\n // Multi-judge: array of judge configs\n if (Array.isArray(rubricOrOptions)) {\n const results = await Promise.all(\n rubricOrOptions.map(async (judgeConfig) => {\n const { rubric: r, ...opts } = judgeConfig;\n return runSingleJudge(received, r, opts);\n })\n );\n\n const allPassed = results.every((r) => r.pass);\n const passCount = results.filter((r) => r.pass).length;\n const summary = `${passCount}/${results.length} judges passed`;\n const details = results.map((r) => r.message).join('\\n');\n\n if (this.isNot) {\n return {\n pass: !allPassed,\n message: () =>\n allPassed\n ? `Expected all judges to fail, but ${summary}`\n : `Judges failed as expected: ${summary}`,\n };\n }\n\n return {\n pass: allPassed,\n message: () => `${summary}\\n${details}`,\n };\n }\n\n // Single judge\n let rubric: RubricSpec | undefined;\n let options: JudgeMatcherOptions;\n\n if (\n typeof rubricOrOptions === 'string' ||\n (typeof rubricOrOptions === 'object' &&\n rubricOrOptions !== null &&\n 'text' in rubricOrOptions)\n ) {\n rubric = rubricOrOptions as RubricSpec;\n options = maybeOptions ?? {};\n } else {\n options = rubricOrOptions;\n }\n\n const result = await runSingleJudge(received, rubric, options);\n\n if (this.isNot) {\n return {\n pass: !result.pass,\n message: () =>\n result.pass\n ? `Expected judge evaluation to fail, but it passed`\n : `Judge evaluation failed as expected`,\n };\n }\n\n return {\n pass: result.pass,\n message: () => result.message,\n };\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","/**\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 * Tool call validators for mcp_host simulation results.\n *\n * These validators extract the tool call trace from an MCPHostSimulationResult\n * and apply assertions against expected call lists and counts.\n */\nimport type { ValidationResult } from './types.js';\nimport type {\n MCPHostSimulationResult,\n LLMToolCall,\n} from '../../evals/mcpHost/mcpHostTypes.js';\n\nexport interface ToolCallExpectation {\n calls: Array<{\n name: string;\n arguments?: Record<string, unknown>;\n required?: boolean;\n }>;\n order?: 'strict' | 'any';\n exclusive?: boolean;\n}\n\nexport interface ToolCallCountOptions {\n min?: number;\n max?: number;\n exact?: number;\n}\n\nfunction isSimulationResult(value: unknown): value is MCPHostSimulationResult {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'success' in value &&\n 'toolCalls' in value &&\n Array.isArray((value as MCPHostSimulationResult).toolCalls)\n );\n}\n\n/**\n * Checks whether a value is a `{ $pattern: \"regex\" }` matcher object.\n */\nfunction isPatternMatcher(\n v: unknown\n): v is { $pattern: string; $flags?: string } {\n return (\n typeof v === 'object' &&\n v !== null &&\n '$pattern' in v &&\n typeof (v as Record<string, unknown>)['$pattern'] === 'string'\n );\n}\n\nfunction partialMatch(\n actual: Record<string, unknown>,\n expected: Record<string, unknown>\n): boolean {\n return Object.entries(expected).every(([k, v]) => {\n const actualVal = actual[k];\n\n // { $pattern: \"regex\", $flags?: \"i\" } — match actual string against regex\n if (isPatternMatcher(v)) {\n if (typeof actualVal !== 'string') return false;\n const re = new RegExp(v.$pattern, v.$flags);\n return re.test(actualVal);\n }\n\n if (\n typeof v === 'object' &&\n v !== null &&\n typeof actualVal === 'object' &&\n actualVal !== null\n ) {\n return partialMatch(\n actualVal as Record<string, unknown>,\n v as Record<string, unknown>\n );\n }\n // Key order in nested objects is handled by recursion — this branch only\n // reaches leaf primitives (strings, numbers, booleans, null) and arrays,\n // where JSON.stringify comparison is correct.\n return JSON.stringify(actualVal) === JSON.stringify(v);\n });\n}\n\nfunction findMatchingCall(\n actual: LLMToolCall[],\n expected: ToolCallExpectation['calls'][number],\n startIndex = 0\n): number {\n for (let i = startIndex; i < actual.length; i++) {\n const call = actual[i]!;\n if (call.name !== expected.name) continue;\n if (\n expected.arguments !== undefined &&\n !partialMatch(call.arguments ?? {}, expected.arguments)\n ) {\n continue;\n }\n return i;\n }\n return -1;\n}\n\n/**\n * Validates tool calls made during an MCP host simulation.\n *\n * @param response - Must be an MCPHostSimulationResult (from mcp_host mode)\n * @param expectation - Expected tool call specification\n */\nexport function validateToolCalls(\n response: unknown,\n expectation: ToolCallExpectation\n): ValidationResult {\n if (!isSimulationResult(response)) {\n return {\n pass: false,\n message:\n 'toolsTriggered expectation requires mcp_host mode — response must be an MCPHostSimulationResult',\n };\n }\n\n const actual = response.toolCalls;\n\n // Compute recall: fraction of required calls that were made\n const requiredCalls = expectation.calls.filter((c) => c.required !== false);\n const calledRequiredCount = requiredCalls.filter(\n (expected) => findMatchingCall(actual, expected) !== -1\n ).length;\n const recall =\n requiredCalls.length > 0 ? calledRequiredCount / requiredCalls.length : 1.0;\n\n // Compute precision: fraction of actual calls that were expected.\n // Always computed so the metric reflects actual tool call efficiency.\n // Whether unexpected calls cause a FAILURE is controlled separately by exclusive=true (lines below).\n const allowedNames = new Set(expectation.calls.map((c) => c.name));\n const precision =\n actual.length > 0\n ? actual.filter((c) => allowedNames.has(c.name)).length / actual.length\n : 1.0;\n\n const metrics = { precision, recall };\n\n const order = expectation.order ?? 'any';\n\n if (order === 'strict') {\n // All calls must appear in the specified sequence\n let searchFrom = 0;\n for (const expected of expectation.calls) {\n const idx = findMatchingCall(actual, expected, searchFrom);\n if (idx === -1) {\n if (expected.required !== false) {\n return {\n pass: false,\n message: `Expected tool '${expected.name}' to be called in sequence (starting from position ${searchFrom}), but it was not found`,\n details: {\n actual: actual.map((c) => c.name),\n expected: expected.name,\n },\n metrics,\n };\n }\n } else {\n searchFrom = idx + 1;\n }\n }\n } else {\n // Any order: each required call must appear somewhere\n const required = expectation.calls.filter((c) => c.required !== false);\n for (const expected of required) {\n const idx = findMatchingCall(actual, expected);\n if (idx === -1) {\n const argsNote =\n expected.arguments !== undefined\n ? ` with args ${JSON.stringify(expected.arguments)}`\n : '';\n return {\n pass: false,\n message: `Expected tool '${expected.name}'${argsNote} to be called, but it was not`,\n details: {\n actual: actual.map((c) => c.name),\n expected: expected.name,\n },\n metrics,\n };\n }\n }\n }\n\n if (expectation.exclusive === true) {\n const unexpected = actual.filter((c) => !allowedNames.has(c.name));\n if (unexpected.length > 0) {\n const names = unexpected.map((c) => `'${c.name}'`).join(', ');\n return {\n pass: false,\n message: `Unexpected tool calls: ${names}. Only ${[...allowedNames].map((n) => `'${n}'`).join(', ')} are allowed`,\n details: {\n actual: actual.map((c) => c.name),\n unexpected: unexpected.map((c) => c.name),\n },\n metrics,\n };\n }\n }\n\n return { pass: true, message: 'All tool call expectations met', metrics };\n}\n\n/**\n * Validates the number of tool calls made during an MCP host simulation.\n *\n * @param response - Must be an MCPHostSimulationResult (from mcp_host mode)\n * @param options - Count constraints (min, max, exact)\n */\nexport function validateToolCallCount(\n response: unknown,\n options: ToolCallCountOptions\n): ValidationResult {\n if (!isSimulationResult(response)) {\n return {\n pass: false,\n message:\n 'toolCallCount expectation requires mcp_host mode — response must be an MCPHostSimulationResult',\n };\n }\n\n const count = response.toolCalls.length;\n const { min, max, exact } = options;\n\n if (exact !== undefined && count !== exact) {\n return {\n pass: false,\n message: `Expected exactly ${exact} tool call(s), but got ${count}`,\n details: { actual: count, expected: exact },\n };\n }\n\n if (min !== undefined && count < min) {\n return {\n pass: false,\n message: `Expected at least ${min} tool call(s), but got ${count}`,\n details: { actual: count, min },\n };\n }\n\n if (max !== undefined && count > max) {\n return {\n pass: false,\n message: `Expected at most ${max} tool call(s), but got ${count}`,\n details: { actual: count, max },\n };\n }\n\n return {\n pass: true,\n message: `Tool call count (${count}) is within expected range`,\n };\n}\n","/**\n * toHaveToolCalls Matcher\n *\n * Validates which tools the LLM called during a mcp_host simulation.\n */\n\nimport { validateToolCalls } from '../validators/toolCalls.js';\nimport type { ToolCallExpectation } from '../validators/toolCalls.js';\n\n/**\n * Creates the toHaveToolCalls matcher function\n */\nexport function toHaveToolCalls(\n this: { isNot: boolean },\n received: unknown,\n expectation: ToolCallExpectation\n) {\n const result = validateToolCalls(received, expectation);\n\n return {\n pass: result.pass,\n message: () => result.message,\n };\n}\n","/**\n * toHaveToolCallCount Matcher\n *\n * Validates the number of tool calls made during a mcp_host simulation.\n */\n\nimport { validateToolCallCount } from '../validators/toolCalls.js';\nimport type { ToolCallCountOptions } from '../validators/toolCalls.js';\n\n/**\n * Creates the toHaveToolCallCount matcher function\n */\nexport function toHaveToolCallCount(\n this: { isNot: boolean },\n received: unknown,\n options: ToolCallCountOptions\n) {\n const result = validateToolCallCount(received, options);\n\n return {\n pass: result.pass,\n message: () => result.message,\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';\nimport { toHaveToolCalls } from './toHaveToolCalls.js';\nimport { toHaveToolCallCount } from './toHaveToolCallCount.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 '@gleanwork/mcp-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 toHaveToolCalls,\n toHaveToolCallCount,\n});\n\n// Re-export types\nexport type {\n JudgeMatcherOptions,\n ToolPredicate,\n PredicateResult,\n} from './types.js';\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 * OAuth 2.1 client credentials configuration for machine-to-machine (CI/CD) authentication.\n * Credentials can be provided here or via MCP_CLIENT_ID/MCP_CLIENT_SECRET environment variables.\n */\nexport interface MCPClientCredentialsConfig {\n /**\n * OAuth client ID (falls back to MCP_CLIENT_ID env var)\n */\n clientId?: string;\n\n /**\n * OAuth client secret (falls back to MCP_CLIENT_SECRET env var)\n */\n clientSecret?: string;\n\n /**\n * Token endpoint URL (required)\n */\n tokenEndpoint?: string;\n\n /**\n * Scopes to request\n */\n scopes?: 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 * OAuth 2.1 client credentials grant for machine-to-machine authentication\n */\n clientCredentials?: MCPClientCredentialsConfig;\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 via stdio transport (local process)\n */\nexport interface StdioMCPConfig {\n /**\n * Transport type discriminant\n */\n transport: 'stdio';\n\n /**\n * Command to execute (required for stdio transport)\n */\n command: string;\n\n /**\n * Command arguments\n */\n args?: Array<string>;\n\n /**\n * Working directory for the command\n */\n cwd?: string;\n\n /**\n * Environment variables to pass to the subprocess.\n * Merged with the current process environment.\n */\n env?: Record<string, string>;\n\n /**\n * Suppress stderr output from the server process.\n * When true, server stderr is ignored instead of inherited.\n */\n quiet?: boolean;\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 * Timeout in milliseconds for MCP tool/list operations. Default: 30000\n */\n callTimeoutMs?: number;\n}\n\n/**\n * Configuration for MCP client connection via HTTP transport (remote server)\n */\nexport interface HttpMCPConfig {\n /**\n * Transport type discriminant\n */\n transport: 'http';\n\n /**\n * Server URL (required for http transport)\n */\n serverUrl: string;\n\n /**\n * HTTP headers (e.g., Authorization)\n */\n headers?: Record<string, string>;\n\n /**\n * Authentication configuration\n */\n auth?: MCPAuthConfig;\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 * Timeout in milliseconds for MCP tool/list operations. Default: 30000\n */\n callTimeoutMs?: number;\n\n /**\n * HTTP proxy configuration. Falls back to HTTPS_PROXY/HTTP_PROXY environment variables.\n */\n proxy?: {\n /**\n * Proxy URL. Credentials can be embedded directly if required:\n * `http://user:pass@proxy.example.com:8080`\n */\n url: string;\n };\n\n /**\n * Number of retry attempts for transient connection failures and 429 rate limit responses.\n * Uses exponential backoff with Retry-After header awareness. Defaults to 0 (no retries).\n */\n retryAttempts?: number;\n\n /**\n * TLS/mTLS configuration for custom certificates or disabling cert validation.\n * File paths should point to PEM-encoded certificate files.\n */\n tls?: {\n /**\n * Path to CA certificate PEM file (for custom/self-signed CAs)\n */\n ca?: string;\n\n /**\n * Path to client certificate PEM file (for mutual TLS)\n */\n cert?: string;\n\n /**\n * Path to client private key PEM file (for mutual TLS)\n */\n key?: string;\n\n /**\n * Whether to reject unauthorized certificates. Defaults to true.\n * Set to false to disable certificate validation (not recommended for production).\n */\n rejectUnauthorized?: boolean;\n };\n}\n\n/**\n * Configuration for MCP client connection.\n *\n * This is a discriminated union — narrow with `isStdioConfig()` or `isHttpConfig()`\n * before accessing transport-specific fields.\n *\n * Supports both stdio (local) and HTTP (remote) transports.\n */\nexport type MCPConfig = StdioMCPConfig | HttpMCPConfig;\n\n/**\n * Zod schema for MCPHostCapabilities\n */\nconst MCPHostCapabilitiesSchema = z.object({\n sampling: z.record(z.string(), 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 MCPClientCredentialsConfig\n */\nconst MCPClientCredentialsConfigSchema = z.object({\n clientId: z.string().optional(),\n clientSecret: z.string().optional(),\n tokenEndpoint: z.string().url('tokenEndpoint must be a valid URL').optional(),\n scopes: z.array(z.string()).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 clientCredentials: MCPClientCredentialsConfigSchema.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 env: z.record(z.string(), z.string()).optional(),\n capabilities: MCPHostCapabilitiesSchema.optional(),\n connectTimeoutMs: z.number().positive().optional(),\n requestTimeoutMs: z.number().positive().optional(),\n callTimeoutMs: z.number().positive().optional(),\n quiet: z.boolean().optional(),\n});\n\n/**\n * Returns true if the hostname refers to the loopback interface\n */\nfunction isLocalhost(hostname: string): boolean {\n return (\n hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '::1'\n );\n}\n\n/**\n * Zod schema for HTTP transport config\n */\nconst HttpConfigSchema = z.object({\n transport: z.literal('http'),\n serverUrl: z\n .string()\n .url('serverUrl must be a valid URL')\n .refine((url) => {\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n return true;\n }\n if (parsed.protocol === 'http:' && !isLocalhost(parsed.hostname)) {\n console.warn(\n `[mcp-server-tester] serverUrl uses http:// for non-localhost address \"${parsed.hostname}\". ` +\n `This transmits tokens unencrypted. Use https:// for remote servers.`\n );\n }\n return true;\n }),\n headers: z.record(z.string(), z.string()).optional(),\n capabilities: MCPHostCapabilitiesSchema.optional(),\n connectTimeoutMs: z.number().positive().optional(),\n requestTimeoutMs: z.number().positive().optional(),\n callTimeoutMs: z.number().positive().optional(),\n auth: MCPAuthConfigSchema.optional(),\n proxy: z\n .object({\n url: z.string().url('proxy.url must be a valid URL'),\n })\n .optional(),\n retryAttempts: z.number().int().min(0).optional(),\n tls: z\n .object({\n ca: z.string().optional(),\n cert: z.string().optional(),\n key: z.string().optional(),\n rejectUnauthorized: z.boolean().optional(),\n })\n .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(config: MCPConfig): config is StdioMCPConfig {\n return config.transport === 'stdio';\n}\n\n/**\n * Type guard to check if a config is for HTTP transport\n */\nexport function isHttpConfig(config: MCPConfig): config is HttpMCPConfig {\n return config.transport === 'http';\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-server-tester logs\n * DEBUG=mcp-server-tester:* npm test\n *\n * # Enable only client logs\n * DEBUG=mcp-server-tester:client npm test\n *\n * # Enable only OAuth logs\n * DEBUG=mcp-server-tester:oauth npm test\n *\n * # Enable HTTP-level trace logging (URL, headers, transport selection)\n * DEBUG=mcp-server-tester:http npx playwright test\n * ```\n */\n\nimport createDebug from 'debug';\n\nconst NAMESPACE = 'mcp-server-tester';\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/**\n * Debug logger for HTTP-level trace logging.\n *\n * Enable with:\n * ```bash\n * DEBUG=mcp-server-tester:http npx playwright test\n * ```\n *\n * Logs: server URL, transport type selected (Streamable HTTP vs SSE),\n * outgoing request header names, and connection outcomes.\n */\nexport const debugHttp = createDebug(`${NAMESPACE}:http`);\n","{\n \"name\": \"@gleanwork/mcp-server-tester\",\n \"version\": \"1.0.1\",\n \"description\": \"Playwright-based testing and evaluation framework for MCP servers\",\n \"keywords\": [\n \"playwright\",\n \"mcp\",\n \"model-context-protocol\",\n \"evals\",\n \"testing\",\n \"llm\",\n \"server-testing\"\n ],\n \"homepage\": \"https://github.com/gleanwork/mcp-server-tester#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/gleanwork/mcp-server-tester/issues\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/gleanwork/mcp-server-tester.git\"\n },\n \"license\": \"MIT\",\n \"author\": \"Glean Contributors\",\n \"type\": \"module\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\",\n \"require\": \"./dist/index.cjs\"\n },\n \"./fixtures/mcp\": {\n \"types\": \"./dist/fixtures/mcp.d.ts\",\n \"import\": \"./dist/fixtures/mcp.js\"\n },\n \"./fixtures/mcpAuth\": {\n \"types\": \"./dist/fixtures/mcpAuth.d.ts\",\n \"import\": \"./dist/fixtures/mcpAuth.js\"\n },\n \"./reporters/mcpReporter\": {\n \"types\": \"./dist/reporters/mcpReporter.d.ts\",\n \"import\": \"./dist/reporters/mcpReporter.js\",\n \"require\": \"./dist/reporters/mcpReporter.cjs\"\n }\n },\n \"main\": \"./dist/index.js\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"bin\": {\n \"mcp-server-tester\": \"./dist/cli/index.js\"\n },\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"build\": \"npm run build:ui && tsup && npm run build:copy-ui\",\n \"build:copy-ui\": \"cp -r src/reporters/ui-dist dist/reporters/\",\n \"build:ui\": \"tsx src/reporters/build-ui.ts\",\n \"dev\": \"tsup --watch\",\n \"dev:ui\": \"tsx src/reporters/build-ui.ts --watch\",\n \"format\": \"prettier --write \\\"**/*.{ts,tsx,json,md}\\\"\",\n \"format:check\": \"prettier --check \\\"**/*.{ts,tsx,json,md}\\\"\",\n \"lint\": \"eslint . --ext .ts,.tsx\",\n \"lint:fix\": \"eslint . --ext .ts,.tsx --fix\",\n \"prepublishOnly\": \"npm run test:all\",\n \"docs:check\": \"markdown-code check\",\n \"docs:sync\": \"markdown-code sync\",\n \"preview-reporter\": \"tsx scripts/preview-reporter.ts\",\n \"test\": \"vitest run\",\n \"test:all\": \"npm run build && npm run format:check && npm run lint && npm run typecheck && npm test\",\n \"test:playwright\": \"playwright test\",\n \"test:watch\": \"vitest\",\n \"typecheck\": \"tsc --noEmit\"\n },\n \"dependencies\": {\n \"@anthropic-ai/claude-agent-sdk\": \"^0.2.71\",\n \"@inkjs/ui\": \"^2.0.0\",\n \"@modelcontextprotocol/sdk\": \"^1.27.1\",\n \"commander\": \"^14.0.2\",\n \"debug\": \"^4.4.3\",\n \"ink\": \"^5.2.1\",\n \"ink-spinner\": \"^5.0.0\",\n \"oauth4webapi\": \"^3.0.0\",\n \"open\": \"^10.1.0\",\n \"react\": \"^18.3.1\",\n \"undici\": \"^7.24.0\",\n \"zod\": \"^4.3.6\"\n },\n \"devDependencies\": {\n \"@ai-sdk/provider-utils\": \"^4.0.15\",\n \"@playwright/test\": \"^1.49.0\",\n \"@release-it-plugins/lerna-changelog\": \"^8.0.1\",\n \"@types/debug\": \"^4.1.12\",\n \"@types/node\": \"^22.10.2\",\n \"@types/react\": \"^18.3.12\",\n \"@types/react-dom\": \"^18.3.1\",\n \"@typescript-eslint/eslint-plugin\": \"^8.18.2\",\n \"@typescript-eslint/parser\": \"^8.18.2\",\n \"@vitest/ui\": \"^4.1.2\",\n \"autoprefixer\": \"^10.4.20\",\n \"bintastic\": \"^4.0.1\",\n \"esbuild\": \"^0.28.0\",\n \"eslint\": \"^8.57.1\",\n \"ink-testing-library\": \"^4.0.0\",\n \"lucide-react\": \"^0.460.0\",\n \"markdown-code\": \"^0.6.1\",\n \"memfs\": \"^4.51.1\",\n \"postcss\": \"^8.4.49\",\n \"prettier\": \"^3.4.2\",\n \"react-dom\": \"^18.3.1\",\n \"recharts\": \"^3.7.0\",\n \"release-it\": \"^19.2.4\",\n \"tailwindcss\": \"^3.4.15\",\n \"tsup\": \"^8.3.5\",\n \"tsx\": \"^4.19.2\",\n \"typescript\": \"^5.7.2\",\n \"vitest\": \"^4.1.2\"\n },\n \"peerDependencies\": {\n \"@ai-sdk/anthropic\": \"^3.0.46\",\n \"@ai-sdk/azure\": \"^3.0.0\",\n \"@ai-sdk/deepseek\": \"^2.0.0\",\n \"@ai-sdk/google\": \"^3.0.0\",\n \"@ai-sdk/google-vertex\": \"^4.0.0\",\n \"@ai-sdk/mistral\": \"^3.0.0\",\n \"@ai-sdk/openai\": \"^3.0.31\",\n \"@ai-sdk/xai\": \"^3.0.0\",\n \"@openrouter/ai-sdk-provider\": \"^2.0.0\",\n \"@playwright/test\": \"^1.40.0\",\n \"ai\": \"^6.0.0\"\n },\n \"peerDependenciesMeta\": {\n \"ai\": {\n \"optional\": true\n },\n \"@ai-sdk/anthropic\": {\n \"optional\": true\n },\n \"@ai-sdk/azure\": {\n \"optional\": true\n },\n \"@ai-sdk/deepseek\": {\n \"optional\": true\n },\n \"@ai-sdk/google\": {\n \"optional\": true\n },\n \"@ai-sdk/google-vertex\": {\n \"optional\": true\n },\n \"@ai-sdk/mistral\": {\n \"optional\": true\n },\n \"@ai-sdk/openai\": {\n \"optional\": true\n },\n \"@ai-sdk/xai\": {\n \"optional\": true\n },\n \"@openrouter/ai-sdk-provider\": {\n \"optional\": true\n }\n },\n \"engines\": {\n \"node\": \">=22.0.0\"\n },\n \"publishConfig\": {\n \"access\": \"public\",\n \"registry\": \"https://registry.npmjs.org\"\n },\n \"release-it\": {\n \"plugins\": {\n \"@release-it-plugins/lerna-changelog\": {\n \"infile\": \"CHANGELOG.md\",\n \"launchEditor\": true\n }\n },\n \"git\": {\n \"tagName\": \"v${version}\"\n },\n \"github\": {\n \"release\": true,\n \"tokenRef\": \"GITHUB_AUTH\"\n }\n },\n \"optionalDependencies\": {\n \"@ai-sdk/anthropic\": \"^3.0.46\",\n \"@ai-sdk/azure\": \"^3.0.0\",\n \"@ai-sdk/deepseek\": \"^2.0.0\",\n \"@ai-sdk/google\": \"^3.0.0\",\n \"@ai-sdk/google-vertex\": \"^4.0.68\",\n \"@ai-sdk/mistral\": \"^3.0.0\",\n \"@ai-sdk/openai\": \"^3.0.31\",\n \"@ai-sdk/xai\": \"^3.0.0\",\n \"@openrouter/ai-sdk-provider\": \"^2.0.0\",\n \"ai\": \"^6.0.97\"\n },\n \"overrides\": {\n \"release-it\": {\n \"undici\": \"6.24.1\"\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 createDebug from 'debug';\nimport type { TokenResult } from './types.js';\n\nconst debug = createDebug('mcp-server-tester:oauth-flow');\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 * Configuration for client credentials grant\n */\nexport interface ClientCredentialsConfig {\n /**\n * Token endpoint URL\n */\n tokenEndpoint: string;\n\n /**\n * OAuth client ID\n */\n clientId: string;\n\n /**\n * OAuth client secret\n */\n clientSecret: string;\n\n /**\n * Scopes to request (optional)\n */\n scopes?: string[];\n}\n\n/**\n * Performs the OAuth 2.1 client credentials grant to obtain an access token.\n * Suitable for CI/CD machine-to-machine authentication.\n *\n * Uses oauth4webapi for spec-compliant request construction and response validation,\n * consistent with how the rest of this module handles OAuth flows.\n *\n * @param config - Client credentials configuration\n * @returns Token result\n */\nexport async function performClientCredentialsFlow(\n config: ClientCredentialsConfig\n): Promise<TokenResult> {\n // Construct minimal AuthorizationServer from the token endpoint URL.\n // oauth4webapi requires an issuer; we use the origin of the token endpoint.\n const tokenEndpointUrl = new URL(config.tokenEndpoint);\n const authServer: oauth.AuthorizationServer = {\n issuer: tokenEndpointUrl.origin,\n token_endpoint: config.tokenEndpoint,\n };\n\n const client: oauth.Client = {\n client_id: config.clientId,\n };\n\n // ClientSecretBasic transmits credentials via Authorization: Basic header (RFC 6749 §2.3.1).\n // This is the recommended method — avoids placing secrets in the request body.\n const clientAuth = oauth.ClientSecretBasic(config.clientSecret);\n\n const parameters: Record<string, string> = {};\n if (config.scopes && config.scopes.length > 0) {\n parameters['scope'] = config.scopes.join(' ');\n }\n\n const response = await oauth.clientCredentialsGrantRequest(\n authServer,\n client,\n clientAuth,\n parameters\n );\n\n const result = await oauth.processClientCredentialsResponse(\n authServer,\n client,\n response\n );\n\n const requestedScopes = new Set(\n config.scopes && config.scopes.length > 0 ? config.scopes : []\n );\n const grantedScopes = new Set(\n (result.scope ?? '').split(' ').filter(Boolean)\n );\n const missingScopes = [...requestedScopes].filter(\n (s) => !grantedScopes.has(s)\n );\n if (\n missingScopes.length > 0 &&\n requestedScopes.size > 0 &&\n grantedScopes.size > 0\n ) {\n debug(\n '[oauth] Warning: Token server granted fewer scopes than requested. Missing: %s',\n missingScopes.join(', ')\n );\n }\n\n return {\n accessToken: result.access_token,\n tokenType: result.token_type,\n expiresIn: result.expires_in,\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","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 { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.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, debugHttp } from '../debug.js';\nimport { ProxyAgent, Agent as UndiciAgent } from 'undici';\nimport { readFileSync } from 'node:fs';\nimport packageJson from '../../package.json' with { type: 'json' };\nimport { performClientCredentialsFlow } from '../auth/oauthFlow.js';\n\n/**\n * Extracts the Retry-After delay in milliseconds from an error response, if present.\n * Returns null if no Retry-After header is found or parseable.\n */\nfunction getRetryAfterDelayMs(err: unknown): number | null {\n const response = (err as Record<string, unknown>)?.response as\n | Response\n | undefined;\n const retryAfter = response?.headers?.get?.('Retry-After');\n if (retryAfter) {\n const seconds = parseInt(retryAfter, 10);\n if (!isNaN(seconds)) return seconds * 1000;\n }\n return null;\n}\n\n/**\n * Returns true if the error is a 429 rate limit response\n */\nfunction isRateLimitError(err: unknown): boolean {\n const response = (err as Record<string, unknown>)?.response as\n | Response\n | undefined;\n return response?.status === 429;\n}\n\n/**\n * Returns true if the error is a transient network error that may succeed on retry\n */\nfunction isTransientNetworkError(err: unknown): boolean {\n if (!(err instanceof Error)) return false;\n const msg = err.message.toLowerCase();\n return (\n msg.includes('econnreset') ||\n msg.includes('econnrefused') ||\n msg.includes('etimedout') ||\n msg.includes('enotfound') ||\n msg.includes('network') ||\n msg.includes('socket hang up') ||\n msg.includes('fetch failed')\n );\n}\n\n/**\n * Returns true if the error should be retried\n */\nfunction isRetryableError(err: unknown): boolean {\n return isTransientNetworkError(err) || isRateLimitError(err);\n}\n\n/**\n * Retries an async operation with exponential backoff.\n * Respects Retry-After headers for 429 rate limit responses.\n */\nasync function retryWithBackoff<T>(\n fn: () => Promise<T>,\n maxAttempts: number\n): Promise<T> {\n let lastErr: unknown;\n for (let attempt = 0; attempt <= maxAttempts; attempt++) {\n try {\n return await fn();\n } catch (err) {\n lastErr = err;\n if (attempt < maxAttempts && isRetryableError(err)) {\n const retryAfterMs = getRetryAfterDelayMs(err);\n const delayMs =\n retryAfterMs !== null\n ? retryAfterMs\n : Math.min(1000 * 2 ** attempt, 30000);\n debugClient(\n 'Retryable error on attempt %d/%d, retrying in %dms: %s',\n attempt + 1,\n maxAttempts + 1,\n delayMs,\n (err as Error).message\n );\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n } else {\n throw err;\n }\n }\n }\n throw lastErr;\n}\n\n/**\n * Tracks undici agents that need to be closed when their associated client is closed.\n * Keyed by Client instance identity.\n */\nconst agentRegistry = new WeakMap<object, UndiciAgent | ProxyAgent>();\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 * Sampling handler callback for LLM sampling requests from the server.\n *\n * When provided, the client will advertise sampling capability to the server.\n * When absent, sampling is removed from declared capabilities so the client\n * does not falsely advertise support it cannot fulfill.\n */\n samplingHandler?: (...args: unknown[]) => unknown;\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 ?? '@gleanwork/mcp-server-tester',\n version: options?.clientInfo?.version ?? packageJson.version,\n },\n {\n capabilities: {\n ...(validatedConfig.capabilities ?? {}),\n // Only advertise sampling if a handler has been registered;\n // declaring sampling capability without a handler violates the MCP spec\n sampling: options?.samplingHandler\n ? (validatedConfig.capabilities?.sampling ?? {})\n : undefined,\n },\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 ...(validatedConfig.env && {\n env: Object.fromEntries(\n Object.entries({ ...process.env, ...validatedConfig.env }).filter(\n (entry): entry is [string, string] => entry[1] !== undefined\n )\n ),\n }),\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(\n transport,\n validatedConfig.connectTimeoutMs !== undefined\n ? { timeout: validatedConfig.connectTimeoutMs }\n : undefined\n );\n } else if (isHttpConfig(validatedConfig)) {\n // Build headers, including static token auth if configured and no authProvider.\n // User-provided headers take precedence over defaults (spread order).\n const headers: Record<string, string> = {\n 'User-Agent': `@gleanwork/mcp-server-tester/${packageJson.version}`,\n ...validatedConfig.headers,\n };\n\n // If using client credentials grant, fetch a token first\n if (validatedConfig.auth?.clientCredentials && !options?.authProvider) {\n const ccConfig = validatedConfig.auth.clientCredentials;\n const clientId = ccConfig.clientId ?? process.env['MCP_CLIENT_ID'];\n const clientSecret =\n ccConfig.clientSecret ?? process.env['MCP_CLIENT_SECRET'];\n\n if (!clientId || !clientSecret) {\n throw new Error(\n 'Client credentials require clientId/clientSecret in config or MCP_CLIENT_ID/MCP_CLIENT_SECRET env vars'\n );\n }\n\n if (!ccConfig.tokenEndpoint) {\n throw new Error(\n 'Client credentials require tokenEndpoint in auth.clientCredentials config'\n );\n }\n\n debugClient('Fetching token via client credentials grant');\n const tokenResult = await performClientCredentialsFlow({\n tokenEndpoint: ccConfig.tokenEndpoint,\n clientId,\n clientSecret,\n scopes: ccConfig.scopes,\n });\n headers.Authorization = `Bearer ${tokenResult.accessToken}`;\n }\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 url = new URL(validatedConfig.serverUrl);\n let requestInit: RequestInit | undefined =\n Object.keys(headers).length > 0 ? { headers } : undefined;\n\n // Apply proxy if configured or available from environment\n const proxyUrl =\n validatedConfig.proxy?.url ??\n process.env['HTTPS_PROXY'] ??\n process.env['HTTP_PROXY'];\n\n if (proxyUrl) {\n const proxyAgent = new ProxyAgent(proxyUrl);\n try {\n const sanitized = new URL(proxyUrl);\n debugClient(\n 'Using proxy: %s://%s:%s',\n sanitized.protocol.slice(0, -1),\n sanitized.hostname,\n sanitized.port\n );\n } catch {\n debugClient('Using proxy (unparseable URL)');\n }\n requestInit = {\n ...requestInit,\n dispatcher: proxyAgent,\n } as unknown as RequestInit;\n }\n\n // Apply TLS configuration if present\n if (validatedConfig.tls) {\n const tlsCfg = validatedConfig.tls;\n try {\n const dispatcher = new UndiciAgent({\n connect: {\n ...(tlsCfg.ca && { ca: readFileSync(tlsCfg.ca) }),\n ...(tlsCfg.cert && { cert: readFileSync(tlsCfg.cert) }),\n ...(tlsCfg.key && { key: readFileSync(tlsCfg.key) }),\n rejectUnauthorized: tlsCfg.rejectUnauthorized ?? true,\n },\n });\n agentRegistry.set(client, dispatcher);\n requestInit = {\n ...requestInit,\n dispatcher,\n } as unknown as RequestInit;\n debugClient('TLS configuration applied');\n } catch (error) {\n const filePath = tlsCfg.ca ?? tlsCfg.cert ?? tlsCfg.key;\n const fileType = tlsCfg.ca\n ? 'CA certificate'\n : tlsCfg.cert\n ? 'client certificate'\n : 'client key';\n throw new Error(\n `Failed to load TLS ${fileType} from ${filePath}: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n } else if (proxyUrl) {\n // Track ProxyAgent for cleanup (already created above in the proxy branch)\n // Re-extract if already set via requestInit\n const existingDispatcher = (\n requestInit as unknown as { dispatcher?: ProxyAgent }\n )?.dispatcher;\n if (existingDispatcher) {\n agentRegistry.set(client, existingDispatcher);\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 debugHttp('Connecting to %s', validatedConfig.serverUrl);\n if (Object.keys(headers).length > 0) {\n debugHttp('Request header names: %O', Object.keys(headers));\n }\n\n const retryAttempts = validatedConfig.retryAttempts ?? 0;\n const connectOptions =\n validatedConfig.connectTimeoutMs !== undefined\n ? { timeout: validatedConfig.connectTimeoutMs }\n : undefined;\n\n // Try Streamable HTTP first (MCP spec 2025-03-26), fall back to SSE (2024-11-05)\n await retryWithBackoff(async () => {\n try {\n debugHttp('Attempting transport: streamableHttp');\n const streamableTransport = new StreamableHTTPClientTransport(url, {\n requestInit,\n authProvider: options?.authProvider,\n });\n await client.connect(streamableTransport, connectOptions);\n debugClient('Connected via Streamable HTTP');\n debugHttp('Connection established via streamableHttp');\n } catch (err) {\n debugHttp(\n 'streamableHttp failed (%s), falling back to SSE',\n (err as Error).message\n );\n debugClient('Streamable HTTP failed, falling back to SSE transport');\n debugHttp('Attempting transport: sse');\n const sseTransport = new SSEClientTransport(url, {\n requestInit,\n authProvider: options?.authProvider,\n });\n await client.connect(sseTransport, connectOptions);\n debugClient('Connected via SSE');\n debugHttp('Connection established via sse');\n }\n }, retryAttempts);\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 // notifications/cancelled requires a specific requestId to be useful — without one\n // the server cannot identify which request to abort. The MCP SDK does not expose\n // outstanding request IDs as a public API, so we close directly and let the\n // transport teardown signal disconnection to the server.\n try {\n // Terminate the MCP session before closing so stateful servers can clean up.\n // TODO: Remove once MCP moves to stateless protocol (see roadmap: https://blog.modelcontextprotocol.io/posts/2026-mcp-roadmap/)\n const transport = client.transport;\n if (transport instanceof StreamableHTTPClientTransport) {\n try {\n await transport.terminateSession();\n } catch (sessionError) {\n debugClient(\n 'Error terminating session: %s',\n sessionError instanceof Error\n ? sessionError.message\n : String(sessionError)\n );\n }\n }\n\n await client.close();\n } catch (error) {\n debugClient(\n 'Error closing client: %s',\n error instanceof Error ? error.message : String(error)\n );\n throw error;\n } finally {\n // Close any pooled undici agent associated with this client\n const agent = agentRegistry.get(client);\n if (agent) {\n agentRegistry.delete(client);\n try {\n await agent.close();\n } catch (agentError) {\n debugClient(\n 'Error closing undici agent: %s',\n (agentError as Error).message\n );\n }\n }\n }\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\nconst DEFAULT_CALL_TIMEOUT_MS = 30_000;\n\nfunction withCallTimeout<T>(\n promise: Promise<T>,\n ms: number,\n opName: string\n): Promise<T> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n return Promise.race([\n promise,\n new Promise<never>((_, reject) => {\n timer = setTimeout(\n () =>\n reject(\n new Error(`MCP operation \"${opName}\" timed out after ${ms}ms`)\n ),\n ms\n );\n }),\n ]).finally(() => clearTimeout(timer));\n}\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 * Timeout in milliseconds for MCP tool/list operations. Default: 30000\n */\n callTimeoutMs?: number;\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, providing a high-level\n * {@link MCPFixtureApi} without requiring Playwright's `test.extend` pattern.\n *\n * Use this when you need to set up an MCP fixture manually — for example in\n * custom fixture hierarchies, non-Playwright test runners (e.g. Vitest,\n * Jest), or when you want to compose the fixture with other lifecycle\n * management logic that doesn't fit the standard `test.extend` model.\n *\n * For the typical Playwright use case, prefer importing `test` and `mcp`\n * directly from `@gleanwork/mcp-server-tester/fixtures/mcp`, which wires\n * this function up automatically.\n *\n * When `testInfo` is provided, all MCP operations are automatically wrapped\n * in `test.step()` calls and attachments are created for the MCP Test\n * Reporter. Omit `testInfo` for lightweight usage outside Playwright.\n *\n * @param client - The MCP client to wrap (created via `createMCPClientForConfig`)\n * @param testInfo - Optional Playwright TestInfo for auto-tracking and reporter attachments\n * @param options - Optional fixture options (authType, project)\n * @returns MCPFixtureApi instance\n *\n * @example\n * ```typescript\n * // Advanced: custom fixture setup inside test.extend\n * const test = base.extend<{ mcp: MCPFixtureApi }>({\n * mcp: async ({}, use, testInfo) => {\n * const client = await createMCPClientForConfig(config);\n * const api = createMCPFixture(client, testInfo, { authType: 'api-token' });\n * await use(api);\n * await closeMCPClient(client);\n * }\n * });\n *\n * // Non-Playwright usage (no reporter attachments)\n * const client = await createMCPClientForConfig(config);\n * const api = createMCPFixture(client);\n * const tools = await api.listTools();\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 const callTimeout = options?.callTimeoutMs ?? DEFAULT_CALL_TIMEOUT_MS;\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 withCallTimeout(\n client.listTools() as Promise<ListToolsResult>,\n callTimeout,\n 'listTools'\n );\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 withCallTimeout(\n client.callTool({\n name,\n arguments: args,\n }) as Promise<CallToolResult>,\n callTimeout,\n `callTool(\"${name}\")`\n );\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 withCallTimeout(\n client.listTools() as Promise<ListToolsResult>,\n callTimeout,\n 'listTools'\n );\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 withCallTimeout(\n client.callTool({\n name,\n arguments: args,\n }) as Promise<CallToolResult>,\n callTimeout,\n `callTool(\"${name}\")`\n );\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((err) => {\n console.error('[MCPFixture] Failed to attach server info:', err);\n });\n\n return result;\n },\n };\n}\n","/**\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: '@gleanwork/mcp-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 * The code verifier is cleared after a successful token exchange — it is\n * single-use per PKCE spec and must not persist beyond the exchange.\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 // Clear codeVerifier after successful token exchange — it's single-use per PKCE spec\n delete state.codeVerifier;\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, mode: 0o700 });\n\n await fs.writeFile(\n this.config.storagePath,\n JSON.stringify(state, null, 2),\n { encoding: 'utf-8', mode: 0o600 }\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-server-tester 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-server-tester 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, mode: 0o700 });\n\n await fs.writeFile(storagePath, JSON.stringify(state, null, 2), {\n encoding: 'utf-8',\n mode: 0o600,\n });\n}\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 * Returns true if the hostname refers to the loopback interface\n */\nfunction isLocalhostUrl(url: string): boolean {\n try {\n const parsed = new URL(url);\n const h = parsed.hostname;\n return h === 'localhost' || h === '127.0.0.1' || h === '::1';\n } catch {\n return false;\n }\n}\n\n/**\n * Validates that critical OAuth endpoints returned by discovery use HTTPS.\n * Localhost URLs are exempt to support local development and testing.\n *\n * @throws Error if any endpoint uses a non-HTTPS, non-localhost scheme\n */\nfunction validateAuthServerEndpoints(authServer: {\n authorization_endpoint?: string;\n token_endpoint?: string;\n issuer?: string;\n}): void {\n const endpoints = [\n { name: 'authorization_endpoint', url: authServer.authorization_endpoint },\n { name: 'token_endpoint', url: authServer.token_endpoint },\n ];\n\n for (const { name, url } of endpoints) {\n if (url && !url.startsWith('https://') && !isLocalhostUrl(url)) {\n throw new Error(\n `OAuth discovery returned an insecure ${name}: \"${url}\". ` +\n `Only HTTPS endpoints are permitted for OAuth flows to prevent token interception.`\n );\n }\n }\n}\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 validateAuthServerEndpoints(metadata);\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-server-tester 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-server-tester login https://api.example.com/mcp\n * const tokens = await loadTokens('https://api.example.com/mcp');\n * if (tokens?.accessToken) {\n * // Use the token — never log raw token values\n * headers.Authorization = `Bearer ${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-server-tester 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 // Note: The `mode` parameter is ignored on Windows (Win32) where file\n // permissions are controlled by NTFS ACLs, not Unix permission bits.\n // On Windows, token files may be readable by other users on the system\n // depending on the directory's inherited ACL. This is a Node.js fs\n // limitation. Windows users should verify %LOCALAPPDATA% permissions manually.\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 * 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-server-tester: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 = '@gleanwork/mcp-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 // Log only non-sensitive parts of the authorization URL.\n // Do NOT log: state, code_challenge, code_challenge_method (security-sensitive).\n debug(\n 'Authorization URL (base): %s',\n `${authUrl.origin}${authUrl.pathname}`\n );\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 { 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';\nimport packageJson from '../../package.json' with { type: 'json' };\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 '@gleanwork/mcp-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-server-tester 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 // Narrow to HTTP config once for all auth-related logic (auth is HTTP-only)\n const httpConfig = isHttpConfig(mcpConfig) ? mcpConfig : null;\n\n // Create auth provider if OAuth authStatePath is configured\n let authProvider: OAuthClientProvider | undefined;\n if (httpConfig?.auth?.oauth?.authStatePath) {\n authProvider = new PlaywrightOAuthClientProvider({\n storagePath: httpConfig.auth.oauth.authStatePath,\n redirectUri:\n httpConfig.auth.oauth.redirectUri ??\n 'http://localhost:3000/oauth/callback',\n clientId: httpConfig.auth.oauth.clientId,\n clientSecret: httpConfig.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 (httpConfig?.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-server-tester login <url>` then run tests\n if (\n httpConfig &&\n !httpConfig.auth?.accessToken &&\n !httpConfig.auth?.oauth?.authStatePath\n ) {\n const cliClient = new CLIOAuthClient({\n mcpServerUrl: httpConfig.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 ...httpConfig,\n auth: {\n ...httpConfig.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: '@gleanwork/mcp-server-tester',\n version: packageJson.version,\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 useConfig = testInfo.project.use as { mcpConfig?: MCPConfig };\n const api = createMCPFixture(mcpClient, testInfo, {\n authType: _mcpFixtureState.resolvedAuthType,\n project: testInfo.project.name,\n callTimeoutMs: useConfig.mcpConfig?.callTimeoutMs,\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"]}