@mcpfn/testing 0.0.1 → 0.0.2
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.
- package/README.md +21 -4
- package/dist/auth.cjs +35 -10
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +30 -1
- package/dist/auth.d.ts +30 -1
- package/dist/auth.js +35 -11
- package/dist/auth.js.map +1 -1
- package/dist/index.cjs +956 -148
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +242 -26
- package/dist/index.d.ts +242 -26
- package/dist/index.js +954 -151
- package/dist/index.js.map +1 -1
- package/dist/playwright.cjs +33 -10
- package/dist/playwright.cjs.map +1 -1
- package/dist/playwright.js +34 -11
- package/dist/playwright.js.map +1 -1
- package/package.json +12 -13
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/assertions.ts","../src/auth-core.ts","../src/mock-oauth-server.ts","../src/client.ts","../src/conformance.ts","../src/host-profiles.ts","../src/scenarios.ts"],"sourcesContent":["import type { Tool } from \"@modelcontextprotocol/sdk/types.js\";\nimport { UriTemplate } from \"@modelcontextprotocol/sdk/shared/uriTemplate.js\";\nimport type { McpFnManifest } from \"@mcpfn/core\";\n\nimport type { McpFnTestClient } from \"./client.js\";\n\nexport function stableJson(value: unknown): string {\n if (Array.isArray(value)) return `[${value.map(stableJson).join(\",\")}]`;\n if (value && typeof value === \"object\") {\n return `{${Object.entries(value as Record<string, unknown>)\n .filter(([, entry]) => entry !== undefined)\n .sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0)\n .map(([key, entry]) => `${JSON.stringify(key)}:${stableJson(entry)}`)\n .join(\",\")}}`;\n }\n return JSON.stringify(value);\n}\n\nexport class McpFnAssertionError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"McpFnAssertionError\";\n }\n}\n\nexport interface AssertManifestContractOptions {\n /** Exact tools expected to be visible for the test client's request context. */\n expectedToolNames?: readonly string[];\n}\n\nexport async function assertManifestContract(\n client: McpFnTestClient<unknown>,\n manifest: McpFnManifest,\n options: AssertManifestContractOptions = {},\n): Promise<Tool[]> {\n const actual = await client.listTools();\n const actualByName = new Map(actual.map((tool) => [tool.name, tool]));\n const manifestByName = new Map(manifest.tools.map((tool) => [tool.name, tool]));\n const expectedNames = [...(\n options.expectedToolNames ?? manifest.tools.map((tool) => tool.name)\n )].sort();\n const unknownExpectedNames = expectedNames.filter((name) => !manifestByName.has(name));\n if (unknownExpectedNames.length) {\n throw new McpFnAssertionError(\n `Expected visible tools are absent from the manifest: ${stableJson(unknownExpectedNames)}`,\n );\n }\n const actualNames = actual.map((tool) => tool.name).sort();\n if (stableJson(expectedNames) !== stableJson(actualNames)) {\n throw new McpFnAssertionError(\n `Tool inventory mismatch\\nexpected: ${stableJson(expectedNames)}\\nactual: ${stableJson(actualNames)}`,\n );\n }\n for (const name of expectedNames) {\n const expected = manifestByName.get(name)!;\n const tool = actualByName.get(expected.name)!;\n const comparableExpected = {\n name: expected.name,\n description: expected.description,\n inputSchema: expected.inputSchema,\n outputSchema: expected.outputSchema,\n annotations: expected.annotations,\n execution: expected.execution,\n icons: expected.icons,\n title: expected.title,\n _meta: expected.metadata,\n };\n const comparableActual = {\n name: tool.name,\n description: tool.description,\n inputSchema: tool.inputSchema,\n outputSchema: tool.outputSchema,\n annotations: tool.annotations,\n execution: tool.execution,\n icons: tool.icons,\n title: tool.title,\n _meta: tool._meta,\n };\n if (stableJson(comparableExpected) !== stableJson(comparableActual)) {\n throw new McpFnAssertionError(\n `Contract mismatch for ${expected.name}\\nexpected: ${stableJson(comparableExpected)}\\nactual: ${stableJson(comparableActual)}`,\n );\n }\n }\n\n const actualCapabilities = client.client.getServerCapabilities() ?? {};\n if (stableJson(manifest.capabilities ?? {}) !== stableJson(actualCapabilities)) {\n throw new McpFnAssertionError(\n `Capability mismatch\\nexpected: ${stableJson(manifest.capabilities ?? {})}\\nactual: ${stableJson(actualCapabilities)}`,\n );\n }\n\n const actualResources = actualCapabilities.resources\n ? await client.listResources()\n : [];\n const comparableResources = actualResources.map(({ _meta, ...resource }) => ({\n ...resource,\n metadata: _meta,\n }));\n const staticResourceUris = new Set(\n (manifest.resources ?? []).map((resource) => resource.uri),\n );\n const resourceTemplates = (manifest.resourceTemplates ?? []).map(\n (template) => new UriTemplate(template.uriTemplate),\n );\n const comparableStaticResources = comparableResources.filter(\n (resource) =>\n staticResourceUris.has(resource.uri) ||\n !resourceTemplates.some((template) => template.match(resource.uri)),\n );\n const expectedResources = (manifest.resources ?? []).map(\n ({ subscribable: _subscribable, ...resource }) => resource,\n );\n if (stableJson(expectedResources) !== stableJson(comparableStaticResources)) {\n throw new McpFnAssertionError(\n `Resource inventory mismatch\\nexpected: ${stableJson(expectedResources)}\\nactual: ${stableJson(comparableStaticResources)}`,\n );\n }\n\n const actualTemplates = actualCapabilities.resources\n ? await client.listResourceTemplates()\n : [];\n const comparableTemplates = actualTemplates.map(({ _meta, ...template }) => ({\n ...template,\n metadata: _meta,\n }));\n const expectedTemplates = (manifest.resourceTemplates ?? []).map(\n ({ subscribable: _subscribable, ...template }) => template,\n );\n if (stableJson(expectedTemplates) !== stableJson(comparableTemplates)) {\n throw new McpFnAssertionError(\n `Resource template inventory mismatch\\nexpected: ${stableJson(expectedTemplates)}\\nactual: ${stableJson(comparableTemplates)}`,\n );\n }\n\n for (const resource of comparableResources) {\n const expected = (manifest.resources ?? []).find(\n (candidate) => candidate.uri === resource.uri,\n ) ?? (manifest.resourceTemplates ?? []).find(\n (candidate) => new UriTemplate(candidate.uriTemplate).match(resource.uri),\n );\n const subscribable = expected?.subscribable === true;\n if (subscribable) {\n try {\n await client.subscribeResource(resource.uri);\n await client.unsubscribeResource(resource.uri);\n } catch (error) {\n throw new McpFnAssertionError(\n `Resource subscription mismatch for ${resource.uri}: expected subscribe and unsubscribe to succeed (${error instanceof Error ? error.message : String(error)})`,\n );\n }\n continue;\n }\n let accepted = false;\n try {\n await client.subscribeResource(resource.uri);\n accepted = true;\n await client.unsubscribeResource(resource.uri).catch(() => undefined);\n } catch {\n // Rejection is the expected behavior for a non-subscribable resource.\n }\n if (accepted) {\n throw new McpFnAssertionError(\n `Resource subscription mismatch for ${resource.uri}: expected subscribe to be rejected`,\n );\n }\n }\n\n const actualPrompts = actualCapabilities.prompts\n ? await client.listPrompts()\n : [];\n const comparablePrompts = actualPrompts.map(({ _meta, ...prompt }) => ({\n ...prompt,\n metadata: _meta,\n }));\n const expectedPrompts = (manifest.prompts ?? []).map(({ argumentsSchema: _schema, ...prompt }) => prompt);\n if (stableJson(expectedPrompts) !== stableJson(comparablePrompts)) {\n throw new McpFnAssertionError(\n `Prompt inventory mismatch\\nexpected: ${stableJson(expectedPrompts)}\\nactual: ${stableJson(comparablePrompts)}`,\n );\n }\n return actual;\n}\n\nexport function assertStructuredTextParity(result: {\n content?: unknown[];\n structuredContent?: Record<string, unknown>;\n}): void {\n if (!result.structuredContent) {\n throw new McpFnAssertionError(\"Tool result has no structuredContent\");\n }\n const text = (result.content ?? []).find(\n (entry): entry is { type: \"text\"; text: string } =>\n !!entry &&\n typeof entry === \"object\" &&\n (entry as { type?: unknown }).type === \"text\" &&\n typeof (entry as { text?: unknown }).text === \"string\",\n )?.text;\n if (!text) {\n throw new McpFnAssertionError(\"Tool result has no text content\");\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n throw new McpFnAssertionError(\"Tool text content is not JSON\");\n }\n if (stableJson(parsed) !== stableJson(result.structuredContent)) {\n throw new McpFnAssertionError(\n \"Tool text content and structuredContent are not equivalent\",\n );\n }\n}\n","export type McpFnAuthCredentialKind = \"api-key\" | \"oauth\";\n\nexport interface McpFnAuthCredential {\n kind: McpFnAuthCredentialKind;\n headers: HeadersInit;\n label?: string;\n dispose?(): void | Promise<void>;\n}\n\nexport interface McpFnAuthCredentialRequest {\n kind: McpFnAuthCredentialKind;\n scopes?: string[];\n resource?: string;\n expiresInSeconds?: number;\n}\n\nexport interface McpFnAuthProviderCapabilities {\n expiration?: boolean;\n resourceBinding?: boolean;\n revocation?: boolean;\n scopes?: boolean;\n}\n\n/**\n * The application-owned seam. Skillplane only needs to map this interface to\n * its existing API-key or OAuth issuance and revocation helpers.\n */\nexport interface McpFnAuthProviderAdapter {\n capabilities?: McpFnAuthProviderCapabilities;\n issue(input: McpFnAuthCredentialRequest): Promise<McpFnAuthCredential>;\n revoke?(credential: McpFnAuthCredential): void | Promise<void>;\n}\n\nexport interface McpFnAuthProbeScenario {\n name:\n | \"missing-credential\"\n | \"invalid-credential\"\n | \"valid-credential\"\n | \"insufficient-scope\"\n | \"expired-credential\"\n | \"missing-resource\"\n | \"wrong-resource\"\n | \"revoked-credential\";\n kind: McpFnAuthCredentialKind;\n}\n\nexport interface McpFnAuthTarget {\n request(\n headers: Headers,\n scenario: McpFnAuthProbeScenario,\n ): Promise<Response>;\n}\n\nexport interface McpFnAuthRegressionOptions {\n kind: McpFnAuthCredentialKind;\n provider: McpFnAuthProviderAdapter;\n target: McpFnAuthTarget;\n requiredScopes?: string[];\n resource?: string;\n wrongResource?: string;\n invalidCredentialHeaders?: HeadersInit;\n /** OAuth failures are required to advertise protected-resource metadata. */\n protectedResourceMetadataUrl?: string;\n expectedAuthenticatedStatuses?: number[];\n verifyAuthenticatedResponse?(\n response: Response,\n credential: McpFnAuthCredential,\n ): void | Promise<void>;\n}\n\nexport interface McpFnAuthScenarioResult {\n name: McpFnAuthProbeScenario[\"name\"];\n status: \"passed\" | \"failed\";\n responseStatus?: number;\n error?: string;\n}\n\nexport interface McpFnBearerChallenge {\n scheme: string;\n parameters: Record<string, string>;\n}\n\nexport class McpFnAuthAssertionError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"McpFnAuthAssertionError\";\n }\n}\n\nfunction expectedStatus(\n response: Response,\n expected: number | number[],\n name: string,\n): void {\n const statuses = Array.isArray(expected) ? expected : [expected];\n if (!statuses.includes(response.status)) {\n throw new McpFnAuthAssertionError(\n `${name} expected HTTP ${statuses.join(\" or \")}, received ${response.status}`,\n );\n }\n}\n\nexport function parseBearerChallenge(\n header: string | null,\n): McpFnBearerChallenge | undefined {\n if (!header) return undefined;\n const matches = [...header.matchAll(/(?:^|,)\\s*([A-Za-z][A-Za-z0-9_-]*)\\s+/g)];\n const selectedIndex = matches.findIndex((entry) => entry[1].toLowerCase() === \"bearer\");\n if (selectedIndex < 0) return undefined;\n const match = matches[selectedIndex];\n const start = (match.index ?? 0) + match[0].length;\n const end = matches[selectedIndex + 1]?.index ?? header.length;\n const parameters: Record<string, string> = {};\n const source = header.slice(start, end);\n const pattern = /([A-Za-z][A-Za-z0-9_-]*)\\s*=\\s*(?:\"((?:[^\"\\\\]|\\\\.)*)\"|([^,\\s]+))/g;\n for (const entry of source.matchAll(pattern)) {\n const quoted = entry[2]?.replace(/\\\\([\"\\\\])/g, \"$1\");\n parameters[entry[1]] = quoted ?? entry[3] ?? \"\";\n }\n return { scheme: match[1], parameters };\n}\n\nexport function assertBearerResourceChallenge(\n response: Response,\n expectedMetadataUrl?: string,\n): McpFnBearerChallenge {\n const challenge = parseBearerChallenge(response.headers.get(\"www-authenticate\"));\n if (!challenge || challenge.scheme.toLowerCase() !== \"bearer\") {\n throw new McpFnAuthAssertionError(\"Expected a Bearer WWW-Authenticate challenge\");\n }\n const metadataUrl = challenge.parameters.resource_metadata;\n if (!metadataUrl) {\n throw new McpFnAuthAssertionError(\n \"Bearer challenge is missing the resource_metadata parameter\",\n );\n }\n try {\n const parsed = new URL(metadataUrl);\n if (!parsed.protocol || !parsed.host) throw new Error(\"not absolute\");\n } catch {\n throw new McpFnAuthAssertionError(\n `Bearer challenge has an invalid resource_metadata URL: ${metadataUrl}`,\n );\n }\n if (expectedMetadataUrl && metadataUrl !== expectedMetadataUrl) {\n throw new McpFnAuthAssertionError(\n `Expected resource_metadata=${expectedMetadataUrl}, received ${metadataUrl}`,\n );\n }\n return challenge;\n}\n\nexport function bearerCredential(\n token: string,\n kind: McpFnAuthCredentialKind = \"oauth\",\n): McpFnAuthCredential {\n return {\n kind,\n headers: { authorization: `Bearer ${token}` },\n };\n}\n\nexport function apiKeyCredential(\n apiKey: string,\n options: { headerName?: string; scheme?: string } = {},\n): McpFnAuthCredential {\n const headerName = options.headerName ?? \"authorization\";\n const value = options.scheme === \"\"\n ? apiKey\n : `${options.scheme ?? \"Bearer\"} ${apiKey}`;\n return { kind: \"api-key\", headers: { [headerName]: value } };\n}\n\nfunction invalidHeaders(options: McpFnAuthRegressionOptions): Headers {\n return new Headers(options.invalidCredentialHeaders ?? {\n authorization: `Bearer mcpfn-invalid-${options.kind}`,\n });\n}\n\nasync function runOne(\n options: McpFnAuthRegressionOptions,\n scenario: McpFnAuthProbeScenario,\n prepare: () => Promise<McpFnAuthCredential | undefined>,\n expected: number | number[],\n): Promise<McpFnAuthScenarioResult> {\n let credential: McpFnAuthCredential | undefined;\n try {\n credential = await prepare();\n const headers = credential\n ? new Headers(credential.headers)\n : scenario.name === \"invalid-credential\"\n ? invalidHeaders(options)\n : new Headers();\n const response = await options.target.request(headers, scenario);\n expectedStatus(response, expected, scenario.name);\n if (\n options.kind === \"oauth\" &&\n scenario.name !== \"valid-credential\"\n ) {\n assertBearerResourceChallenge(\n response,\n options.protectedResourceMetadataUrl,\n );\n }\n if (scenario.name === \"valid-credential\" && credential) {\n await options.verifyAuthenticatedResponse?.(response.clone(), credential);\n }\n return {\n name: scenario.name,\n status: \"passed\",\n responseStatus: response.status,\n };\n } catch (error) {\n return {\n name: scenario.name,\n status: \"failed\",\n error: error instanceof Error ? error.message : String(error),\n };\n } finally {\n await credential?.dispose?.();\n }\n}\n\n/** Runs the common API-key or OAuth resource-server regression matrix. */\nexport async function runAuthRegressionSuite(\n options: McpFnAuthRegressionOptions,\n): Promise<McpFnAuthScenarioResult[]> {\n const issue = (overrides: Partial<McpFnAuthCredentialRequest> = {}) =>\n options.provider.issue({\n kind: options.kind,\n scopes: options.requiredScopes,\n resource: options.resource,\n ...overrides,\n });\n const results: McpFnAuthScenarioResult[] = [];\n results.push(await runOne(\n options,\n { name: \"missing-credential\", kind: options.kind },\n async () => undefined,\n 401,\n ));\n results.push(await runOne(\n options,\n { name: \"invalid-credential\", kind: options.kind },\n async () => undefined,\n 401,\n ));\n results.push(await runOne(\n options,\n { name: \"valid-credential\", kind: options.kind },\n () => issue(),\n options.expectedAuthenticatedStatuses ?? [200, 201, 202, 204],\n ));\n\n const capabilities = options.provider.capabilities ?? {};\n if (capabilities.scopes && options.requiredScopes?.length) {\n results.push(await runOne(\n options,\n { name: \"insufficient-scope\", kind: options.kind },\n () => issue({ scopes: [] }),\n 403,\n ));\n }\n if (capabilities.expiration) {\n results.push(await runOne(\n options,\n { name: \"expired-credential\", kind: options.kind },\n () => issue({ expiresInSeconds: -60 }),\n 401,\n ));\n }\n if (capabilities.resourceBinding && options.resource) {\n results.push(await runOne(\n options,\n { name: \"missing-resource\", kind: options.kind },\n () => issue({ resource: undefined }),\n 401,\n ));\n }\n if (capabilities.resourceBinding && options.wrongResource) {\n results.push(await runOne(\n options,\n { name: \"wrong-resource\", kind: options.kind },\n () => issue({ resource: options.wrongResource }),\n 401,\n ));\n }\n if (capabilities.revocation && options.provider.revoke) {\n results.push(await runOne(\n options,\n { name: \"revoked-credential\", kind: options.kind },\n async () => {\n const credential = await issue();\n await options.provider.revoke?.(credential);\n return credential;\n },\n 401,\n ));\n }\n return results;\n}\n\nexport async function assertAuthRegressionSuite(\n options: McpFnAuthRegressionOptions,\n): Promise<McpFnAuthScenarioResult[]> {\n const results = await runAuthRegressionSuite(options);\n const failures = results.filter((result) => result.status === \"failed\");\n if (failures.length) {\n throw new McpFnAuthAssertionError(\n failures.map((failure) => `${failure.name}: ${failure.error}`).join(\"\\n\"),\n );\n }\n return results;\n}\n\nexport interface McpFnFetchAuthTargetOptions {\n url: string | URL;\n fetch?: typeof globalThis.fetch;\n requestInit?: RequestInit | ((scenario: McpFnAuthProbeScenario) => RequestInit);\n}\n\n/** Creates a protected MCP initialize probe suitable for local or deployed endpoints. */\nexport function createFetchAuthTarget(\n options: McpFnFetchAuthTargetOptions,\n): McpFnAuthTarget {\n const fetchImplementation = options.fetch ?? globalThis.fetch;\n if (!fetchImplementation) {\n throw new Error(\"A fetch implementation is required\");\n }\n return {\n async request(authHeaders, scenario) {\n const configured = typeof options.requestInit === \"function\"\n ? options.requestInit(scenario)\n : options.requestInit ?? {};\n const headers = new Headers(configured.headers);\n headers.set(\"accept\", \"application/json, text/event-stream\");\n headers.set(\"content-type\", \"application/json\");\n authHeaders.forEach((value, name) => headers.set(name, value));\n return fetchImplementation(options.url, {\n method: \"POST\",\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: `mcpfn-auth-${scenario.name}`,\n method: \"initialize\",\n params: {\n protocolVersion: \"2025-11-25\",\n capabilities: {},\n clientInfo: { name: \"mcpfn-auth-test\", version: \"1.0.0\" },\n },\n }),\n ...configured,\n headers,\n });\n },\n };\n}\n\nexport const MCPFN_OAUTH_EXTENSION_GRANTS = {\n jwtBearer: \"urn:ietf:params:oauth:grant-type:jwt-bearer\",\n deviceCode: \"urn:ietf:params:oauth:grant-type:device_code\",\n generic: \"urn:example:params:oauth:grant-type:extension\",\n} as const;\n\nexport interface McpFnOAuthClientMetadata extends Record<string, unknown> {\n client_id: string;\n client_name?: string;\n redirect_uris: string[];\n response_types: string[];\n grant_types: string[];\n token_endpoint_auth_method: string;\n}\n\nexport interface McpFnOAuthClientMetadataFixtureOptions {\n clientId: string;\n redirectUris: string[];\n clientName?: string;\n extraGrantTypes?: string[];\n extraMetadata?: Record<string, unknown>;\n}\n\nexport interface McpFnOAuthClientMetadataVariants {\n basic: McpFnOAuthClientMetadata;\n jwtBearerExtension: McpFnOAuthClientMetadata;\n deviceCodeExtension: McpFnOAuthClientMetadata;\n genericExtension: McpFnOAuthClientMetadata;\n}\n\nexport function createOAuthClientMetadataFixture(\n options: McpFnOAuthClientMetadataFixtureOptions,\n): McpFnOAuthClientMetadata {\n return {\n ...options.extraMetadata,\n client_id: new URL(options.clientId).toString(),\n client_name: options.clientName ?? \"McpFn OAuth test client\",\n redirect_uris: [...new Set(options.redirectUris.map((uri) => new URL(uri).toString()))],\n response_types: [\"code\"],\n grant_types: [\n \"authorization_code\",\n \"refresh_token\",\n ...new Set(options.extraGrantTypes ?? []),\n ],\n token_endpoint_auth_method: \"none\",\n };\n}\n\nexport function createOAuthClientMetadataVariants(\n baseUrl: string | URL,\n redirectUri = new URL(\"/callback\", baseUrl).toString(),\n): McpFnOAuthClientMetadataVariants {\n const base = new URL(baseUrl);\n const fixture = (name: string, extraGrantTypes: string[] = []) =>\n createOAuthClientMetadataFixture({\n clientId: new URL(`/client-metadata/${name}`, base).toString(),\n redirectUris: [redirectUri],\n clientName: `McpFn ${name} client`,\n extraGrantTypes,\n });\n return {\n basic: fixture(\"basic\"),\n jwtBearerExtension: fixture(\"jwt-bearer-extension\", [MCPFN_OAUTH_EXTENSION_GRANTS.jwtBearer]),\n deviceCodeExtension: fixture(\"device-code-extension\", [MCPFN_OAUTH_EXTENSION_GRANTS.deviceCode]),\n genericExtension: fixture(\"generic-extension\", [MCPFN_OAUTH_EXTENSION_GRANTS.generic]),\n };\n}\n\n/**\n * Validates compatibility with authorization-code + PKCE without applying a\n * closed-world allowlist to unrelated grant types advertised by the client.\n */\nexport function assertAuthorizationCodeClientMetadata(\n metadata: McpFnOAuthClientMetadata,\n expectedClientId?: string,\n): McpFnOAuthClientMetadata {\n if (expectedClientId && metadata.client_id !== new URL(expectedClientId).toString()) {\n throw new McpFnAuthAssertionError(\"OAuth client metadata client_id does not match its document URL\");\n }\n if (!metadata.response_types.includes(\"code\")) {\n throw new McpFnAuthAssertionError(\"OAuth client metadata does not support response_type=code\");\n }\n if (!metadata.grant_types.includes(\"authorization_code\")) {\n throw new McpFnAuthAssertionError(\"OAuth client metadata does not support authorization_code\");\n }\n if (!metadata.redirect_uris.length) {\n throw new McpFnAuthAssertionError(\"OAuth client metadata must declare at least one redirect URI\");\n }\n return metadata;\n}\n","import { createHash, randomBytes, randomUUID } from \"node:crypto\";\nimport { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport type { AddressInfo } from \"node:net\";\n\nimport type { AuthInfo } from \"@modelcontextprotocol/sdk/server/auth/types.js\";\n\nimport {\n assertAuthorizationCodeClientMetadata,\n createOAuthClientMetadataVariants,\n type McpFnOAuthClientMetadataVariants,\n} from \"./auth-core.js\";\n\ninterface AuthorizationCodeRecord {\n clientId: string;\n redirectUri: string;\n codeChallenge: string;\n scopes: string[];\n resource?: string;\n expiresAt: number;\n used: boolean;\n}\n\ninterface AccessTokenRecord {\n clientId: string;\n scopes: string[];\n resource?: string;\n expiresAt: number;\n revoked: boolean;\n}\n\ninterface RefreshTokenRecord {\n clientId: string;\n scopes: string[];\n resource?: string;\n expiresAt: number;\n revoked: boolean;\n}\n\nexport interface McpFnMockOAuthServerOptions {\n issuer: string | URL;\n clientId?: string;\n redirectUris?: string[];\n scopesSupported?: string[];\n accessTokenLifetimeSeconds?: number;\n authorizationCodeLifetimeSeconds?: number;\n refreshTokenLifetimeSeconds?: number;\n clock?: () => number;\n}\n\nexport interface McpFnMockOAuthTokenSet {\n access_token: string;\n token_type: \"Bearer\";\n expires_in: number;\n refresh_token: string;\n scope: string;\n resource?: string;\n}\n\nexport interface McpFnPkcePair {\n verifier: string;\n challenge: string;\n method: \"S256\";\n}\n\nexport interface McpFnOAuthCallback {\n url: string;\n parameters: Record<string, string>;\n}\n\nfunction base64Url(value: Buffer): string {\n return value.toString(\"base64url\");\n}\n\nexport function createPkcePair(): McpFnPkcePair {\n const verifier = base64Url(randomBytes(48));\n return {\n verifier,\n challenge: createHash(\"sha256\").update(verifier).digest(\"base64url\"),\n method: \"S256\",\n };\n}\n\nfunction uniqueScopes(value: string | null | undefined): string[] {\n return [...new Set((value ?? \"\").split(/\\s+/).filter(Boolean))].sort();\n}\n\nfunction json(status: number, body: unknown): Response {\n return Response.json(body, {\n status,\n headers: { \"cache-control\": \"no-store\" },\n });\n}\n\nfunction oauthError(status: number, error: string, description: string): Response {\n return json(status, { error, error_description: description });\n}\n\nfunction escapeHtml(value: string): string {\n return value\n .replaceAll(\"&\", \"&\")\n .replaceAll('\"', \""\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\">\", \">\");\n}\n\nfunction formValue(form: URLSearchParams, name: string): string | undefined {\n const value = form.get(name);\n return value === null || value === \"\" ? undefined : value;\n}\n\nexport class McpFnMockOAuthAuthorizationServer {\n readonly issuer: URL;\n readonly clientId: string;\n readonly redirectUris: string[];\n readonly scopesSupported: string[];\n readonly clientMetadata: McpFnOAuthClientMetadataVariants;\n\n private readonly codes = new Map<string, AuthorizationCodeRecord>();\n private readonly accessTokens = new Map<string, AccessTokenRecord>();\n private readonly refreshTokens = new Map<string, RefreshTokenRecord>();\n private readonly callbacks: McpFnOAuthCallback[] = [];\n private readonly clock: () => number;\n private readonly accessTokenLifetimeSeconds: number;\n private readonly authorizationCodeLifetimeSeconds: number;\n private readonly refreshTokenLifetimeSeconds: number;\n\n constructor(options: McpFnMockOAuthServerOptions) {\n this.issuer = new URL(options.issuer);\n this.issuer.pathname = this.issuer.pathname.replace(/\\/?$/, \"/\");\n this.clientId = options.clientId ?? \"mcpfn-playwright\";\n this.redirectUris = options.redirectUris?.map((uri) => new URL(uri).toString()) ?? [\n new URL(\"callback\", this.issuer).toString(),\n ];\n this.scopesSupported = [...new Set(options.scopesSupported ?? [\"mcp:read\", \"mcp:write\"])].sort();\n this.clock = options.clock ?? Date.now;\n this.accessTokenLifetimeSeconds = options.accessTokenLifetimeSeconds ?? 300;\n this.authorizationCodeLifetimeSeconds = options.authorizationCodeLifetimeSeconds ?? 120;\n this.refreshTokenLifetimeSeconds = options.refreshTokenLifetimeSeconds ?? 3_600;\n this.clientMetadata = createOAuthClientMetadataVariants(\n this.issuer,\n this.redirectUris[0],\n );\n }\n\n get metadataUrl(): string {\n return new URL(\".well-known/oauth-authorization-server\", this.issuer).toString();\n }\n\n get authorizationEndpoint(): string {\n return new URL(\"authorize\", this.issuer).toString();\n }\n\n get tokenEndpoint(): string {\n return new URL(\"token\", this.issuer).toString();\n }\n\n get revocationEndpoint(): string {\n return new URL(\"revoke\", this.issuer).toString();\n }\n\n get callbackUrl(): string {\n return this.redirectUris[0];\n }\n\n clientMetadataUrl(\n variant: keyof McpFnOAuthClientMetadataVariants,\n ): string {\n return this.clientMetadata[variant].client_id;\n }\n\n authorizationUrl(input: {\n clientId?: string;\n redirectUri?: string;\n codeChallenge: string;\n state?: string;\n scopes?: string[];\n resource?: string;\n extraParameters?: Record<string, string>;\n }): string {\n const url = new URL(this.authorizationEndpoint);\n url.searchParams.set(\"response_type\", \"code\");\n url.searchParams.set(\"client_id\", input.clientId ?? this.clientId);\n url.searchParams.set(\"redirect_uri\", input.redirectUri ?? this.callbackUrl);\n url.searchParams.set(\"code_challenge\", input.codeChallenge);\n url.searchParams.set(\"code_challenge_method\", \"S256\");\n url.searchParams.set(\"scope\", (input.scopes ?? [\"mcp:read\"]).join(\" \"));\n if (input.state) url.searchParams.set(\"state\", input.state);\n if (input.resource) url.searchParams.set(\"resource\", input.resource);\n for (const [name, value] of Object.entries(input.extraParameters ?? {})) {\n url.searchParams.set(name, value);\n }\n return url.toString();\n }\n\n latestCallback(): McpFnOAuthCallback | undefined {\n return this.callbacks.at(-1);\n }\n\n expireAccessToken(token: string): void {\n const record = this.accessTokens.get(token);\n if (record) record.expiresAt = this.nowSeconds() - 1;\n }\n\n revokeToken(token: string): void {\n const access = this.accessTokens.get(token);\n if (access) access.revoked = true;\n const refresh = this.refreshTokens.get(token);\n if (refresh) refresh.revoked = true;\n }\n\n async verifyAccessToken(token: string): Promise<AuthInfo> {\n const record = this.accessTokens.get(token);\n if (!record || record.revoked || record.expiresAt <= this.nowSeconds()) {\n throw new Error(\"Invalid access token\");\n }\n return {\n token,\n clientId: record.clientId,\n scopes: record.scopes,\n expiresAt: record.expiresAt,\n ...(record.resource ? { resource: new URL(record.resource) } : {}),\n };\n }\n\n async handle(request: Request): Promise<Response> {\n const url = new URL(request.url);\n const path = url.pathname.replace(this.issuer.pathname.replace(/\\/$/, \"\"), \"\") || \"/\";\n if (request.method === \"GET\" && path === \"/.well-known/oauth-authorization-server\") {\n return json(200, {\n issuer: this.issuer.toString(),\n authorization_endpoint: this.authorizationEndpoint,\n token_endpoint: this.tokenEndpoint,\n revocation_endpoint: this.revocationEndpoint,\n response_types_supported: [\"code\"],\n grant_types_supported: [\"authorization_code\", \"refresh_token\"],\n code_challenge_methods_supported: [\"S256\"],\n token_endpoint_auth_methods_supported: [\"none\"],\n scopes_supported: this.scopesSupported,\n });\n }\n\n if (request.method === \"GET\" && path.startsWith(\"/client-metadata/\")) {\n const metadata = Object.values(this.clientMetadata)\n .find((candidate) => new URL(candidate.client_id).pathname === url.pathname);\n return metadata ? json(200, metadata) : json(404, { error: \"not_found\" });\n }\n\n if (request.method === \"GET\" && path === \"/authorize\") {\n return this.authorize(url);\n }\n if (request.method === \"POST\" && path === \"/token\") {\n return this.token(await request.text());\n }\n if (request.method === \"POST\" && path === \"/revoke\") {\n return this.revoke(await request.text());\n }\n if (request.method === \"GET\" && path === \"/callback\") {\n const parameters = Object.fromEntries(url.searchParams);\n this.callbacks.push({ url: url.toString(), parameters });\n return new Response(\n `<!doctype html><html><body><main><h1>OAuth callback received</h1><pre>${escapeHtml(JSON.stringify(parameters, null, 2))}</pre></main></body></html>`,\n { headers: { \"content-type\": \"text/html; charset=utf-8\" } },\n );\n }\n return json(404, { error: \"not_found\" });\n }\n\n private nowSeconds(): number {\n return Math.floor(this.clock() / 1_000);\n }\n\n private resolveClient(clientId: string): { clientId: string; redirectUris: string[] } | undefined {\n if (clientId === this.clientId) {\n return { clientId, redirectUris: this.redirectUris };\n }\n const metadata = Object.values(this.clientMetadata)\n .find((candidate) => candidate.client_id === clientId);\n if (!metadata) return undefined;\n assertAuthorizationCodeClientMetadata(metadata, clientId);\n return { clientId, redirectUris: metadata.redirect_uris };\n }\n\n private authorize(url: URL): Response {\n const clientId = url.searchParams.get(\"client_id\") ?? \"\";\n const redirectUri = url.searchParams.get(\"redirect_uri\") ?? \"\";\n const client = this.resolveClient(clientId);\n if (!client) return oauthError(400, \"invalid_client\", \"Unknown OAuth client\");\n if (!client.redirectUris.includes(redirectUri)) {\n return oauthError(400, \"invalid_request\", \"redirect_uri is not registered\");\n }\n if (url.searchParams.get(\"response_type\") !== \"code\") {\n return this.authorizationRedirect(url, redirectUri, \"unsupported_response_type\");\n }\n const codeChallenge = url.searchParams.get(\"code_challenge\");\n if (!codeChallenge || url.searchParams.get(\"code_challenge_method\") !== \"S256\") {\n return this.authorizationRedirect(url, redirectUri, \"invalid_request\", \"PKCE S256 is required\");\n }\n const requestedScopes = uniqueScopes(url.searchParams.get(\"scope\"));\n if (requestedScopes.some((scope) => !this.scopesSupported.includes(scope))) {\n return this.authorizationRedirect(url, redirectUri, \"invalid_scope\");\n }\n const decision = url.searchParams.get(\"decision\");\n if (!decision) {\n const hidden = [...url.searchParams]\n .filter(([name]) => name !== \"decision\")\n .map(([name, value]) => `<input type=\"hidden\" name=\"${escapeHtml(name)}\" value=\"${escapeHtml(value)}\">`)\n .join(\"\");\n return new Response(\n `<!doctype html><html><body><main><h1>Authorize MCP client</h1><p>${escapeHtml(clientId)}</p><form method=\"get\" action=\"${escapeHtml(this.authorizationEndpoint)}\">${hidden}<button name=\"decision\" value=\"approve\">Approve</button><button name=\"decision\" value=\"deny\">Deny</button></form></main></body></html>`,\n { headers: { \"content-type\": \"text/html; charset=utf-8\", \"cache-control\": \"no-store\" } },\n );\n }\n if (decision === \"deny\") {\n return this.authorizationRedirect(url, redirectUri, \"access_denied\");\n }\n if (decision !== \"approve\") {\n return oauthError(400, \"invalid_request\", \"Unknown authorization decision\");\n }\n const code = `mcpfn_code_${randomUUID()}`;\n this.codes.set(code, {\n clientId,\n redirectUri,\n codeChallenge,\n scopes: requestedScopes,\n resource: url.searchParams.get(\"resource\") ?? undefined,\n expiresAt: this.nowSeconds() + this.authorizationCodeLifetimeSeconds,\n used: false,\n });\n const callback = new URL(redirectUri);\n callback.searchParams.set(\"code\", code);\n const state = url.searchParams.get(\"state\");\n if (state) callback.searchParams.set(\"state\", state);\n return Response.redirect(callback, 302);\n }\n\n private authorizationRedirect(\n requestUrl: URL,\n redirectUri: string,\n error: string,\n description?: string,\n ): Response {\n const callback = new URL(redirectUri);\n callback.searchParams.set(\"error\", error);\n if (description) callback.searchParams.set(\"error_description\", description);\n const state = requestUrl.searchParams.get(\"state\");\n if (state) callback.searchParams.set(\"state\", state);\n return Response.redirect(callback, 302);\n }\n\n private token(source: string): Response {\n const form = new URLSearchParams(source);\n const grantType = formValue(form, \"grant_type\");\n if (grantType === \"authorization_code\") return this.exchangeAuthorizationCode(form);\n if (grantType === \"refresh_token\") return this.exchangeRefreshToken(form);\n return oauthError(400, \"unsupported_grant_type\", \"The grant type is not supported\");\n }\n\n private exchangeAuthorizationCode(form: URLSearchParams): Response {\n const code = formValue(form, \"code\");\n const record = code ? this.codes.get(code) : undefined;\n if (!record || record.used || record.expiresAt <= this.nowSeconds()) {\n return oauthError(400, \"invalid_grant\", \"Authorization code is invalid or expired\");\n }\n if (\n formValue(form, \"client_id\") !== record.clientId ||\n formValue(form, \"redirect_uri\") !== record.redirectUri\n ) {\n return oauthError(400, \"invalid_grant\", \"Authorization code binding does not match\");\n }\n const verifier = formValue(form, \"code_verifier\");\n const challenge = verifier\n ? createHash(\"sha256\").update(verifier).digest(\"base64url\")\n : undefined;\n if (challenge !== record.codeChallenge) {\n return oauthError(400, \"invalid_grant\", \"PKCE verification failed\");\n }\n record.used = true;\n return json(200, this.issueTokenSet(record));\n }\n\n private exchangeRefreshToken(form: URLSearchParams): Response {\n const refreshToken = formValue(form, \"refresh_token\");\n const record = refreshToken ? this.refreshTokens.get(refreshToken) : undefined;\n if (!record || record.revoked || record.expiresAt <= this.nowSeconds()) {\n return oauthError(400, \"invalid_grant\", \"Refresh token is invalid or expired\");\n }\n if (formValue(form, \"client_id\") !== record.clientId) {\n return oauthError(400, \"invalid_grant\", \"Refresh token client binding does not match\");\n }\n const requestedScopes = form.has(\"scope\")\n ? uniqueScopes(form.get(\"scope\"))\n : record.scopes;\n if (requestedScopes.some((scope) => !record.scopes.includes(scope))) {\n return oauthError(400, \"invalid_scope\", \"Refresh cannot increase granted scopes\");\n }\n record.revoked = true;\n return json(200, this.issueTokenSet({ ...record, scopes: requestedScopes }));\n }\n\n private issueTokenSet(\n input: Pick<AccessTokenRecord, \"clientId\" | \"scopes\" | \"resource\">,\n ): McpFnMockOAuthTokenSet {\n const accessToken = `mcpfn_access_${randomUUID()}`;\n const refreshToken = `mcpfn_refresh_${randomUUID()}`;\n this.accessTokens.set(accessToken, {\n ...input,\n expiresAt: this.nowSeconds() + this.accessTokenLifetimeSeconds,\n revoked: false,\n });\n this.refreshTokens.set(refreshToken, {\n ...input,\n expiresAt: this.nowSeconds() + this.refreshTokenLifetimeSeconds,\n revoked: false,\n });\n return {\n access_token: accessToken,\n token_type: \"Bearer\",\n expires_in: this.accessTokenLifetimeSeconds,\n refresh_token: refreshToken,\n scope: input.scopes.join(\" \"),\n ...(input.resource ? { resource: input.resource } : {}),\n };\n }\n\n private revoke(source: string): Response {\n const token = new URLSearchParams(source).get(\"token\");\n if (token) this.revokeToken(token);\n return new Response(null, { status: 200 });\n }\n}\n\nexport interface McpFnStartedMockOAuthServer {\n origin: string;\n oauth: McpFnMockOAuthAuthorizationServer;\n close(): Promise<void>;\n}\n\nexport interface McpFnStartMockOAuthServerOptions\n extends Omit<McpFnMockOAuthServerOptions, \"issuer\"> {\n hostname?: string;\n port?: number;\n}\n\nasync function toRequest(req: IncomingMessage, origin: string): Promise<Request> {\n const chunks: Buffer[] = [];\n for await (const chunk of req) chunks.push(Buffer.from(chunk));\n const headers = new Headers();\n for (const [name, value] of Object.entries(req.headers)) {\n if (Array.isArray(value)) {\n for (const entry of value) headers.append(name, entry);\n } else if (value !== undefined) {\n headers.set(name, value);\n }\n }\n const body = chunks.length ? Buffer.concat(chunks) : undefined;\n const init: RequestInit & { duplex?: \"half\" } = {\n method: req.method,\n headers,\n ...(body ? { body, duplex: \"half\" } : {}),\n };\n return new Request(new URL(req.url ?? \"/\", origin), init);\n}\n\nasync function writeResponse(res: ServerResponse, response: Response): Promise<void> {\n res.statusCode = response.status;\n response.headers.forEach((value, name) => res.setHeader(name, value));\n res.end(Buffer.from(await response.arrayBuffer()));\n}\n\nexport async function startMockOAuthAuthorizationServer(\n options: McpFnStartMockOAuthServerOptions = {},\n): Promise<McpFnStartedMockOAuthServer> {\n let oauth: McpFnMockOAuthAuthorizationServer | undefined;\n let origin = \"\";\n const server = createServer(async (req, res) => {\n try {\n if (!oauth) throw new Error(\"Mock OAuth server is not initialized\");\n await writeResponse(res, await oauth.handle(await toRequest(req, origin)));\n } catch {\n res.statusCode = 500;\n res.setHeader(\"content-type\", \"application/json\");\n res.end(JSON.stringify({\n error: \"server_error\",\n error_description: \"Internal Server Error\",\n }));\n }\n });\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject);\n server.listen(options.port ?? 0, options.hostname ?? \"127.0.0.1\", () => {\n server.off(\"error\", reject);\n resolve();\n });\n });\n const address = server.address() as AddressInfo;\n origin = `http://${address.address.includes(\":\") ? `[${address.address}]` : address.address}:${address.port}`;\n oauth = new McpFnMockOAuthAuthorizationServer({ ...options, issuer: origin });\n return {\n origin,\n oauth,\n close: () => new Promise<void>((resolve, reject) => {\n server.close((error) => error ? reject(error) : resolve());\n }),\n };\n}\n","import { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { InMemoryTransport } from \"@modelcontextprotocol/sdk/inMemory.js\";\nimport type {\n CallToolResult,\n ClientCapabilities,\n CompleteRequest,\n CompleteResult,\n CreateTaskResult,\n GetPromptResult,\n ListTasksResult,\n Prompt,\n ReadResourceResult,\n Resource,\n ResourceTemplate,\n Task,\n Tool,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport {\n CallToolResultSchema,\n CreateTaskResultSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { McpFnServer } from \"@mcpfn/core\";\n\nexport interface McpFnTestClientOptions {\n capabilities?: ClientCapabilities;\n /** Install roots, sampling, elicitation, or notification handlers before initialize. */\n configure?(client: Client): void | Promise<void>;\n}\n\nexport class McpFnTestClient<TContext = undefined> {\n readonly client: Client;\n private readonly server: McpFnServer<TContext>;\n private closed = false;\n\n private constructor(client: Client, server: McpFnServer<TContext>) {\n this.client = client;\n this.server = server;\n }\n\n static async connect<TContext>(\n server: McpFnServer<TContext>,\n info = { name: \"mcpfn-test-client\", version: \"1.0.0\" },\n options: McpFnTestClientOptions = {},\n ): Promise<McpFnTestClient<TContext>> {\n const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();\n const client = new Client(info, { capabilities: options.capabilities ?? {} });\n await options.configure?.(client);\n await server.connect(serverTransport);\n await client.connect(clientTransport);\n return new McpFnTestClient(client, server);\n }\n\n async listTools(): Promise<Tool[]> {\n const values: Tool[] = [];\n let cursor: string | undefined;\n do {\n const page = await this.client.listTools(cursor ? { cursor } : undefined);\n values.push(...page.tools);\n cursor = page.nextCursor;\n } while (cursor);\n return values;\n }\n\n async callTool(\n name: string,\n args: Record<string, unknown> = {},\n ): Promise<CallToolResult> {\n return (await this.client.callTool({ name, arguments: args })) as CallToolResult;\n }\n\n async createToolTask(\n name: string,\n args: Record<string, unknown> = {},\n options: { ttl?: number } = {},\n ): Promise<CreateTaskResult> {\n return this.client.request(\n {\n method: \"tools/call\",\n params: { name, arguments: args, task: options },\n },\n CreateTaskResultSchema,\n );\n }\n\n getTask(taskId: string): Promise<Task> {\n return this.client.experimental.tasks.getTask(taskId);\n }\n\n getTaskResult(taskId: string): Promise<CallToolResult> {\n return this.client.experimental.tasks.getTaskResult(\n taskId,\n CallToolResultSchema,\n ) as Promise<CallToolResult>;\n }\n\n listTasks(cursor?: string): Promise<ListTasksResult> {\n return this.client.experimental.tasks.listTasks(cursor);\n }\n\n cancelTask(taskId: string): Promise<Task> {\n return this.client.experimental.tasks.cancelTask(taskId);\n }\n\n async listResources(): Promise<Resource[]> {\n const values: Resource[] = [];\n let cursor: string | undefined;\n do {\n const page = await this.client.listResources(cursor ? { cursor } : undefined);\n values.push(...page.resources);\n cursor = page.nextCursor;\n } while (cursor);\n return values;\n }\n\n async listResourceTemplates(): Promise<ResourceTemplate[]> {\n const values: ResourceTemplate[] = [];\n let cursor: string | undefined;\n do {\n const page = await this.client.listResourceTemplates(cursor ? { cursor } : undefined);\n values.push(...page.resourceTemplates);\n cursor = page.nextCursor;\n } while (cursor);\n return values;\n }\n\n readResource(uri: string): Promise<ReadResourceResult> {\n return this.client.readResource({ uri });\n }\n\n async subscribeResource(uri: string): Promise<void> {\n await this.client.subscribeResource({ uri });\n }\n\n async unsubscribeResource(uri: string): Promise<void> {\n await this.client.unsubscribeResource({ uri });\n }\n\n async listPrompts(): Promise<Prompt[]> {\n const values: Prompt[] = [];\n let cursor: string | undefined;\n do {\n const page = await this.client.listPrompts(cursor ? { cursor } : undefined);\n values.push(...page.prompts);\n cursor = page.nextCursor;\n } while (cursor);\n return values;\n }\n\n getPrompt(\n name: string,\n args?: Record<string, string>,\n ): Promise<GetPromptResult> {\n return this.client.getPrompt({ name, ...(args ? { arguments: args } : {}) });\n }\n\n complete(params: CompleteRequest[\"params\"]): Promise<CompleteResult> {\n return this.client.complete(params);\n }\n\n async close(): Promise<void> {\n if (this.closed) return;\n this.closed = true;\n await this.client.close().catch(() => undefined);\n await this.server.close().catch(() => undefined);\n }\n}\n","import { spawn } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport path from \"node:path\";\n\nexport const OFFICIAL_CONFORMANCE_VERSION = \"0.1.16\";\n\nexport interface OfficialConformanceOptions {\n url: string;\n suite?: \"active\" | \"all\" | \"pending\";\n scenario?: string;\n expectedFailures?: string;\n outputDir?: string;\n specVersion?: string;\n verbose?: boolean;\n cwd?: string;\n stdio?: \"inherit\" | \"pipe\";\n}\n\nexport interface OfficialConformanceResult {\n exitCode: number;\n stdout: string;\n stderr: string;\n}\n\nfunction npxInvocation(args: string[]): { command: string; args: string[] } {\n if (process.platform !== \"win32\") return { command: \"npx\", args };\n const npmExecPath = process.env.npm_execpath;\n const candidates = [\n npmExecPath ? path.join(path.dirname(npmExecPath), \"npx-cli.js\") : undefined,\n path.resolve(path.dirname(process.execPath), \"node_modules/npm/bin/npx-cli.js\"),\n path.resolve(path.dirname(process.execPath), \"../lib/node_modules/npm/bin/npx-cli.js\"),\n ].filter((candidate): candidate is string => Boolean(candidate));\n const npxCli = candidates.find((candidate) => existsSync(candidate));\n if (!npxCli) {\n throw new Error(\"Unable to locate npm's npx-cli.js for the official MCP conformance runner\");\n }\n return { command: process.execPath, args: [npxCli, ...args] };\n}\n\nexport function buildOfficialConformanceArgs(\n options: OfficialConformanceOptions,\n): string[] {\n const args = [\n \"--yes\",\n `@modelcontextprotocol/conformance@${OFFICIAL_CONFORMANCE_VERSION}`,\n \"server\",\n \"--url\",\n options.url,\n ];\n if (options.suite) args.push(\"--suite\", options.suite);\n if (options.scenario) args.push(\"--scenario\", options.scenario);\n if (options.expectedFailures) {\n args.push(\"--expected-failures\", options.expectedFailures);\n }\n if (options.outputDir) args.push(\"--output-dir\", options.outputDir);\n if (options.specVersion) args.push(\"--spec-version\", options.specVersion);\n if (options.verbose) args.push(\"--verbose\");\n return args;\n}\n\nexport async function runOfficialConformance(\n options: OfficialConformanceOptions,\n): Promise<OfficialConformanceResult> {\n const nodeMajor = Number.parseInt(process.versions.node.split(\".\")[0] ?? \"0\", 10);\n if (nodeMajor < 22) {\n throw new Error(\n `Official MCP conformance ${OFFICIAL_CONFORMANCE_VERSION} requires Node.js 22 or newer; current runtime is ${process.versions.node}`,\n );\n }\n const args = buildOfficialConformanceArgs(options);\n const invocation = npxInvocation(args);\n\n return await new Promise<OfficialConformanceResult>((resolve, reject) => {\n const child = spawn(invocation.command, invocation.args, {\n cwd: options.cwd,\n env: {\n ...process.env,\n PATH: [path.dirname(process.execPath), process.env.PATH]\n .filter(Boolean)\n .join(path.delimiter),\n },\n stdio: options.stdio === \"inherit\" ? \"inherit\" : \"pipe\",\n });\n let stdout = \"\";\n let stderr = \"\";\n child.stdout?.on(\"data\", (chunk) => {\n stdout += chunk.toString();\n });\n child.stderr?.on(\"data\", (chunk) => {\n stderr += chunk.toString();\n });\n child.once(\"error\", reject);\n child.once(\"close\", (code) => {\n resolve({ exitCode: code ?? 1, stdout, stderr });\n });\n });\n}\n","import {\n MCP_APP_EXTENSION_ID,\n type McpFnManifest,\n} from \"@mcpfn/core\";\n\nexport type McpFnServerFeature =\n | \"tools\"\n | \"resources\"\n | \"prompts\"\n | \"completions\"\n | \"tasks\"\n | \"logging\";\n\nexport interface McpFnHostProfile {\n id: string;\n name: string;\n protocolVersions: string[];\n serverFeatures: McpFnServerFeature[];\n clientFeatures?: {\n sampling?: boolean;\n elicitation?: Array<\"form\" | \"url\">;\n roots?: boolean;\n };\n extensions?: string[];\n}\n\nexport interface McpFnHostCompatibilityIssue {\n severity: \"incompatible\" | \"degraded\";\n code: string;\n path: string;\n message: string;\n}\n\nexport interface McpFnHostCompatibilityResult {\n status: \"compatible\" | \"degraded\" | \"incompatible\";\n compatible: boolean;\n issues: McpFnHostCompatibilityIssue[];\n}\n\nexport const MCPFN_HOST_PROFILES = {\n toolsOnly: {\n id: \"mcpfn/tools-only\",\n name: \"Tools-only MCP host\",\n protocolVersions: [\"2025-03-26\", \"2025-06-18\", \"2025-11-25\"],\n serverFeatures: [\"tools\"],\n },\n fullProtocol: {\n id: \"mcpfn/full-protocol\",\n name: \"Full protocol MCP host\",\n protocolVersions: [\"2025-03-26\", \"2025-06-18\", \"2025-11-25\"],\n serverFeatures: [\"tools\", \"resources\", \"prompts\", \"completions\", \"tasks\", \"logging\"],\n clientFeatures: { sampling: true, elicitation: [\"form\", \"url\"], roots: true },\n },\n mcpApps: {\n id: \"mcpfn/mcp-apps\",\n name: \"Full protocol host with MCP Apps\",\n protocolVersions: [\"2025-11-25\"],\n serverFeatures: [\"tools\", \"resources\", \"prompts\", \"completions\", \"tasks\", \"logging\"],\n clientFeatures: { sampling: true, elicitation: [\"form\", \"url\"], roots: true },\n extensions: [MCP_APP_EXTENSION_ID],\n },\n} as const satisfies Record<string, McpFnHostProfile>;\n\nexport function checkHostCompatibility(\n manifest: McpFnManifest,\n profile: McpFnHostProfile,\n): McpFnHostCompatibilityResult {\n const issues: McpFnHostCompatibilityIssue[] = [];\n if (\n manifest.protocolVersions?.length &&\n !manifest.protocolVersions.some((version) => profile.protocolVersions.includes(version))\n ) {\n issues.push({\n severity: \"incompatible\",\n code: \"protocol-version-mismatch\",\n path: \"protocolVersions\",\n message: `${profile.name} and ${manifest.server.name} have no protocol version in common`,\n });\n }\n\n const supportedServerFeatures = new Set(profile.serverFeatures);\n for (const feature of Object.keys(manifest.capabilities ?? {})) {\n if (\n feature === \"experimental\" ||\n supportedServerFeatures.has(feature as McpFnServerFeature)\n ) continue;\n issues.push({\n severity: \"degraded\",\n code: \"server-feature-unavailable\",\n path: `capabilities.${feature}`,\n message: `${profile.name} will not expose the server's ${feature} feature`,\n });\n }\n\n const required = manifest.clientRequirements;\n if (required?.sampling && !profile.clientFeatures?.sampling) {\n issues.push({\n severity: \"incompatible\",\n code: \"sampling-required\",\n path: \"clientRequirements.sampling\",\n message: `${manifest.server.name} requires client sampling`,\n });\n }\n if (required?.roots && !profile.clientFeatures?.roots) {\n issues.push({\n severity: \"incompatible\",\n code: \"roots-required\",\n path: \"clientRequirements.roots\",\n message: `${manifest.server.name} requires client roots`,\n });\n }\n for (const mode of required?.elicitation ?? []) {\n if (!profile.clientFeatures?.elicitation?.includes(mode)) {\n issues.push({\n severity: \"incompatible\",\n code: \"elicitation-required\",\n path: `clientRequirements.elicitation.${mode}`,\n message: `${manifest.server.name} requires ${mode} elicitation`,\n });\n }\n }\n\n const extensions = new Set(profile.extensions ?? []);\n for (const [extension, configuration] of Object.entries(manifest.extensions ?? {})) {\n if (extensions.has(extension)) continue;\n const requiredExtension =\n configuration && typeof configuration === \"object\" &&\n (configuration as Record<string, unknown>).required === true;\n issues.push({\n severity: requiredExtension ? \"incompatible\" : \"degraded\",\n code: \"extension-unavailable\",\n path: `extensions.${extension}`,\n message: `${profile.name} does not support ${extension}`,\n });\n }\n\n if (!extensions.has(MCP_APP_EXTENSION_ID)) {\n for (const tool of manifest.tools) {\n const ui = tool.metadata?.ui as { visibility?: string[] } | undefined;\n if (ui?.visibility?.length && !ui.visibility.includes(\"model\")) {\n issues.push({\n severity: \"incompatible\",\n code: \"app-only-tool-unavailable\",\n path: `tools.${tool.name}.metadata.ui.visibility`,\n message: `${tool.name} is app-only but ${profile.name} does not support MCP Apps`,\n });\n }\n }\n }\n\n issues.sort((left, right) => left.path.localeCompare(right.path) || left.code.localeCompare(right.code));\n const status = issues.some((issue) => issue.severity === \"incompatible\")\n ? \"incompatible\"\n : issues.length\n ? \"degraded\"\n : \"compatible\";\n return { status, compatible: status !== \"incompatible\", issues };\n}\n","import type { CallToolResult } from \"@modelcontextprotocol/sdk/types.js\";\n\nimport { McpFnAssertionError, assertStructuredTextParity, stableJson } from \"./assertions.js\";\nimport type { McpFnTestClient } from \"./client.js\";\n\nexport interface McpFnScenario {\n name: string;\n tool: string;\n arguments?: Record<string, unknown>;\n expect?: {\n isError?: boolean;\n structuredContent?: unknown;\n structuredTextParity?: boolean;\n };\n verify?(result: CallToolResult): void | Promise<void>;\n}\n\nexport interface McpFnScenarioResult {\n name: string;\n tool: string;\n status: \"passed\" | \"failed\";\n durationMs: number;\n error?: string;\n}\n\nexport async function runScenarios(\n client: McpFnTestClient<unknown>,\n scenarios: McpFnScenario[],\n): Promise<McpFnScenarioResult[]> {\n const results: McpFnScenarioResult[] = [];\n for (const scenario of scenarios) {\n const startedAt = performance.now();\n try {\n const result = await client.callTool(scenario.tool, scenario.arguments);\n if (result.isError && scenario.expect?.isError === undefined) {\n throw new McpFnAssertionError(\n \"Tool returned isError=true without an explicit expect.isError=true assertion\",\n );\n }\n if (\n scenario.expect?.isError !== undefined &&\n Boolean(result.isError) !== scenario.expect.isError\n ) {\n throw new McpFnAssertionError(\n `Expected isError=${scenario.expect.isError}, received ${Boolean(result.isError)}`,\n );\n }\n if (\n scenario.expect &&\n Object.prototype.hasOwnProperty.call(scenario.expect, \"structuredContent\") &&\n stableJson(result.structuredContent) !==\n stableJson(scenario.expect.structuredContent)\n ) {\n throw new McpFnAssertionError(\n `Structured result mismatch\\nexpected: ${stableJson(scenario.expect.structuredContent)}\\nactual: ${stableJson(result.structuredContent)}`,\n );\n }\n if (scenario.expect?.structuredTextParity) {\n assertStructuredTextParity(result);\n }\n await scenario.verify?.(result);\n results.push({\n name: scenario.name,\n tool: scenario.tool,\n status: \"passed\",\n durationMs: performance.now() - startedAt,\n });\n } catch (error) {\n results.push({\n name: scenario.name,\n tool: scenario.tool,\n status: \"failed\",\n durationMs: performance.now() - startedAt,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n return results;\n}\n"],"mappings":"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","names":["path"]}
|
|
1
|
+
{"version":3,"sources":["../src/assertions.ts","../src/auth-core.ts","../src/mock-oauth-server.ts","../src/client.ts","../src/conformance.ts","../src/host-profiles.ts","../src/scenarios.ts","../src/suite.ts"],"sourcesContent":["import type { Tool } from \"@modelcontextprotocol/sdk/types.js\";\nimport { UriTemplate } from \"@modelcontextprotocol/sdk/shared/uriTemplate.js\";\nimport type { McpFnManifest } from \"@mcpfn/core\";\n\nimport type { McpFnTestClient } from \"./client.js\";\n\nexport function stableJson(value: unknown): string {\n if (Array.isArray(value)) return `[${value.map(stableJson).join(\",\")}]`;\n if (value && typeof value === \"object\") {\n return `{${Object.entries(value as Record<string, unknown>)\n .filter(([, entry]) => entry !== undefined)\n .sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0)\n .map(([key, entry]) => `${JSON.stringify(key)}:${stableJson(entry)}`)\n .join(\",\")}}`;\n }\n return JSON.stringify(value);\n}\n\nexport class McpFnAssertionError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"McpFnAssertionError\";\n }\n}\n\nexport interface AssertManifestContractOptions {\n /** Exact tools expected to be visible for the test client's request context. */\n expectedToolNames?: readonly string[];\n}\n\nexport async function assertManifestContract(\n client: McpFnTestClient<unknown>,\n manifest: McpFnManifest,\n options: AssertManifestContractOptions = {},\n): Promise<Tool[]> {\n const actual = await client.listTools();\n const actualByName = new Map(actual.map((tool) => [tool.name, tool]));\n const manifestByName = new Map(manifest.tools.map((tool) => [tool.name, tool]));\n const expectedNames = [...(\n options.expectedToolNames ?? manifest.tools.map((tool) => tool.name)\n )].sort();\n const unknownExpectedNames = expectedNames.filter((name) => !manifestByName.has(name));\n if (unknownExpectedNames.length) {\n throw new McpFnAssertionError(\n `Expected visible tools are absent from the manifest: ${stableJson(unknownExpectedNames)}`,\n );\n }\n const actualNames = actual.map((tool) => tool.name).sort();\n if (stableJson(expectedNames) !== stableJson(actualNames)) {\n throw new McpFnAssertionError(\n `Tool inventory mismatch\\nexpected: ${stableJson(expectedNames)}\\nactual: ${stableJson(actualNames)}`,\n );\n }\n for (const name of expectedNames) {\n const expected = manifestByName.get(name)!;\n const tool = actualByName.get(expected.name)!;\n const comparableExpected = {\n name: expected.name,\n description: expected.description,\n inputSchema: expected.inputSchema,\n outputSchema: expected.outputSchema,\n annotations: expected.annotations,\n execution: expected.execution,\n icons: expected.icons,\n title: expected.title,\n _meta: expected.metadata,\n };\n const comparableActual = {\n name: tool.name,\n description: tool.description,\n inputSchema: tool.inputSchema,\n outputSchema: tool.outputSchema,\n annotations: tool.annotations,\n execution: tool.execution,\n icons: tool.icons,\n title: tool.title,\n _meta: tool._meta,\n };\n if (stableJson(comparableExpected) !== stableJson(comparableActual)) {\n throw new McpFnAssertionError(\n `Contract mismatch for ${expected.name}\\nexpected: ${stableJson(comparableExpected)}\\nactual: ${stableJson(comparableActual)}`,\n );\n }\n }\n\n const actualCapabilities = client.client.getServerCapabilities() ?? {};\n if (stableJson(manifest.capabilities ?? {}) !== stableJson(actualCapabilities)) {\n throw new McpFnAssertionError(\n `Capability mismatch\\nexpected: ${stableJson(manifest.capabilities ?? {})}\\nactual: ${stableJson(actualCapabilities)}`,\n );\n }\n\n const actualResources = actualCapabilities.resources\n ? await client.listResources()\n : [];\n const comparableResources = actualResources.map(({ _meta, ...resource }) => ({\n ...resource,\n metadata: _meta,\n }));\n const staticResourceUris = new Set(\n (manifest.resources ?? []).map((resource) => resource.uri),\n );\n const resourceTemplates = (manifest.resourceTemplates ?? []).map(\n (template) => new UriTemplate(template.uriTemplate),\n );\n const comparableStaticResources = comparableResources.filter(\n (resource) =>\n staticResourceUris.has(resource.uri) ||\n !resourceTemplates.some((template) => template.match(resource.uri)),\n );\n const expectedResources = (manifest.resources ?? []).map(\n ({ subscribable: _subscribable, ...resource }) => resource,\n );\n if (stableJson(expectedResources) !== stableJson(comparableStaticResources)) {\n throw new McpFnAssertionError(\n `Resource inventory mismatch\\nexpected: ${stableJson(expectedResources)}\\nactual: ${stableJson(comparableStaticResources)}`,\n );\n }\n\n const actualTemplates = actualCapabilities.resources\n ? await client.listResourceTemplates()\n : [];\n const comparableTemplates = actualTemplates.map(({ _meta, ...template }) => ({\n ...template,\n metadata: _meta,\n }));\n const expectedTemplates = (manifest.resourceTemplates ?? []).map(\n ({ subscribable: _subscribable, ...template }) => template,\n );\n if (stableJson(expectedTemplates) !== stableJson(comparableTemplates)) {\n throw new McpFnAssertionError(\n `Resource template inventory mismatch\\nexpected: ${stableJson(expectedTemplates)}\\nactual: ${stableJson(comparableTemplates)}`,\n );\n }\n\n for (const resource of comparableResources) {\n const expected = (manifest.resources ?? []).find(\n (candidate) => candidate.uri === resource.uri,\n ) ?? (manifest.resourceTemplates ?? []).find(\n (candidate) => new UriTemplate(candidate.uriTemplate).match(resource.uri),\n );\n const subscribable = expected?.subscribable === true;\n if (subscribable) {\n try {\n await client.subscribeResource(resource.uri);\n await client.unsubscribeResource(resource.uri);\n } catch (error) {\n throw new McpFnAssertionError(\n `Resource subscription mismatch for ${resource.uri}: expected subscribe and unsubscribe to succeed (${error instanceof Error ? error.message : String(error)})`,\n );\n }\n continue;\n }\n let accepted = false;\n try {\n await client.subscribeResource(resource.uri);\n accepted = true;\n await client.unsubscribeResource(resource.uri).catch(() => undefined);\n } catch {\n // Rejection is the expected behavior for a non-subscribable resource.\n }\n if (accepted) {\n throw new McpFnAssertionError(\n `Resource subscription mismatch for ${resource.uri}: expected subscribe to be rejected`,\n );\n }\n }\n\n const actualPrompts = actualCapabilities.prompts\n ? await client.listPrompts()\n : [];\n const comparablePrompts = actualPrompts.map(({ _meta, ...prompt }) => ({\n ...prompt,\n metadata: _meta,\n }));\n const expectedPrompts = (manifest.prompts ?? []).map(({ argumentsSchema: _schema, ...prompt }) => prompt);\n if (stableJson(expectedPrompts) !== stableJson(comparablePrompts)) {\n throw new McpFnAssertionError(\n `Prompt inventory mismatch\\nexpected: ${stableJson(expectedPrompts)}\\nactual: ${stableJson(comparablePrompts)}`,\n );\n }\n return actual;\n}\n\nexport function assertStructuredTextParity(result: {\n content?: unknown[];\n structuredContent?: Record<string, unknown>;\n}): void {\n if (!result.structuredContent) {\n throw new McpFnAssertionError(\"Tool result has no structuredContent\");\n }\n const text = (result.content ?? []).find(\n (entry): entry is { type: \"text\"; text: string } =>\n !!entry &&\n typeof entry === \"object\" &&\n (entry as { type?: unknown }).type === \"text\" &&\n typeof (entry as { text?: unknown }).text === \"string\",\n )?.text;\n if (!text) {\n throw new McpFnAssertionError(\"Tool result has no text content\");\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n throw new McpFnAssertionError(\"Tool text content is not JSON\");\n }\n if (stableJson(parsed) !== stableJson(result.structuredContent)) {\n throw new McpFnAssertionError(\n \"Tool text content and structuredContent are not equivalent\",\n );\n }\n}\n","export type McpFnAuthCredentialKind = \"api-key\" | \"oauth\";\n\nexport interface McpFnAuthCredential {\n kind: McpFnAuthCredentialKind;\n headers: HeadersInit;\n label?: string;\n dispose?(): void | Promise<void>;\n}\n\nexport interface McpFnAuthCredentialRequest {\n kind: McpFnAuthCredentialKind;\n scopes?: string[];\n resource?: string;\n expiresInSeconds?: number;\n}\n\nexport interface McpFnAuthProviderCapabilities {\n expiration?: boolean;\n resourceBinding?: boolean;\n revocation?: boolean;\n scopes?: boolean;\n}\n\n/**\n * The application-owned seam. Skillplane only needs to map this interface to\n * its existing API-key or OAuth issuance and revocation helpers.\n */\nexport interface McpFnAuthProviderAdapter {\n capabilities?: McpFnAuthProviderCapabilities;\n issue(input: McpFnAuthCredentialRequest): Promise<McpFnAuthCredential>;\n revoke?(credential: McpFnAuthCredential): void | Promise<void>;\n}\n\nexport interface McpFnAuthProbeScenario {\n name:\n | \"missing-credential\"\n | \"invalid-credential\"\n | \"valid-credential\"\n | \"insufficient-scope\"\n | \"expired-credential\"\n | \"missing-resource\"\n | \"wrong-resource\"\n | \"revoked-credential\";\n kind: McpFnAuthCredentialKind;\n}\n\nexport interface McpFnAuthTarget {\n request(\n headers: Headers,\n scenario: McpFnAuthProbeScenario,\n ): Promise<Response>;\n}\n\nexport interface McpFnAuthRegressionOptions {\n kind: McpFnAuthCredentialKind;\n provider: McpFnAuthProviderAdapter;\n target: McpFnAuthTarget;\n requiredScopes?: string[];\n resource?: string;\n wrongResource?: string;\n invalidCredentialHeaders?: HeadersInit;\n /** OAuth failures are required to advertise protected-resource metadata. */\n protectedResourceMetadataUrl?: string;\n expectedAuthenticatedStatuses?: number[];\n verifyAuthenticatedResponse?(\n response: Response,\n credential: McpFnAuthCredential,\n ): void | Promise<void>;\n}\n\nexport interface McpFnAuthScenarioResult {\n name: McpFnAuthProbeScenario[\"name\"];\n status: \"passed\" | \"failed\";\n responseStatus?: number;\n error?: string;\n}\n\nexport interface McpFnBearerChallenge {\n scheme: string;\n parameters: Record<string, string>;\n}\n\nexport class McpFnAuthAssertionError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"McpFnAuthAssertionError\";\n }\n}\n\nfunction expectedStatus(\n response: Response,\n expected: number | number[],\n name: string,\n): void {\n const statuses = Array.isArray(expected) ? expected : [expected];\n if (!statuses.includes(response.status)) {\n throw new McpFnAuthAssertionError(\n `${name} expected HTTP ${statuses.join(\" or \")}, received ${response.status}`,\n );\n }\n}\n\nexport function parseBearerChallenge(\n header: string | null,\n): McpFnBearerChallenge | undefined {\n if (!header) return undefined;\n const matches = [...header.matchAll(/(?:^|,)\\s*([A-Za-z][A-Za-z0-9_-]*)\\s+/g)];\n const selectedIndex = matches.findIndex((entry) => entry[1].toLowerCase() === \"bearer\");\n if (selectedIndex < 0) return undefined;\n const match = matches[selectedIndex];\n const start = (match.index ?? 0) + match[0].length;\n const end = matches[selectedIndex + 1]?.index ?? header.length;\n const parameters: Record<string, string> = {};\n const source = header.slice(start, end);\n const pattern = /([A-Za-z][A-Za-z0-9_-]*)\\s*=\\s*(?:\"((?:[^\"\\\\]|\\\\.)*)\"|([^,\\s]+))/g;\n for (const entry of source.matchAll(pattern)) {\n const quoted = entry[2]?.replace(/\\\\([\"\\\\])/g, \"$1\");\n parameters[entry[1]] = quoted ?? entry[3] ?? \"\";\n }\n return { scheme: match[1], parameters };\n}\n\nexport function assertBearerResourceChallenge(\n response: Response,\n expectedMetadataUrl?: string,\n): McpFnBearerChallenge {\n const challenge = parseBearerChallenge(response.headers.get(\"www-authenticate\"));\n if (!challenge || challenge.scheme.toLowerCase() !== \"bearer\") {\n throw new McpFnAuthAssertionError(\"Expected a Bearer WWW-Authenticate challenge\");\n }\n const metadataUrl = challenge.parameters.resource_metadata;\n if (!metadataUrl) {\n throw new McpFnAuthAssertionError(\n \"Bearer challenge is missing the resource_metadata parameter\",\n );\n }\n try {\n const parsed = new URL(metadataUrl);\n if (!parsed.protocol || !parsed.host) throw new Error(\"not absolute\");\n } catch {\n throw new McpFnAuthAssertionError(\n `Bearer challenge has an invalid resource_metadata URL: ${metadataUrl}`,\n );\n }\n if (expectedMetadataUrl && metadataUrl !== expectedMetadataUrl) {\n throw new McpFnAuthAssertionError(\n `Expected resource_metadata=${expectedMetadataUrl}, received ${metadataUrl}`,\n );\n }\n return challenge;\n}\n\nexport function bearerCredential(\n token: string,\n kind: McpFnAuthCredentialKind = \"oauth\",\n): McpFnAuthCredential {\n return {\n kind,\n headers: { authorization: `Bearer ${token}` },\n };\n}\n\nexport function apiKeyCredential(\n apiKey: string,\n options: { headerName?: string; scheme?: string } = {},\n): McpFnAuthCredential {\n const headerName = options.headerName ?? \"authorization\";\n const value = options.scheme === \"\"\n ? apiKey\n : `${options.scheme ?? \"Bearer\"} ${apiKey}`;\n return { kind: \"api-key\", headers: { [headerName]: value } };\n}\n\nfunction invalidHeaders(options: McpFnAuthRegressionOptions): Headers {\n return new Headers(options.invalidCredentialHeaders ?? {\n authorization: `Bearer mcpfn-invalid-${options.kind}`,\n });\n}\n\nasync function runOne(\n options: McpFnAuthRegressionOptions,\n scenario: McpFnAuthProbeScenario,\n prepare: () => Promise<McpFnAuthCredential | undefined>,\n expected: number | number[],\n): Promise<McpFnAuthScenarioResult> {\n let credential: McpFnAuthCredential | undefined;\n try {\n credential = await prepare();\n const headers = credential\n ? new Headers(credential.headers)\n : scenario.name === \"invalid-credential\"\n ? invalidHeaders(options)\n : new Headers();\n const response = await options.target.request(headers, scenario);\n expectedStatus(response, expected, scenario.name);\n if (\n options.kind === \"oauth\" &&\n scenario.name !== \"valid-credential\"\n ) {\n assertBearerResourceChallenge(\n response,\n options.protectedResourceMetadataUrl,\n );\n }\n if (scenario.name === \"valid-credential\" && credential) {\n await options.verifyAuthenticatedResponse?.(response.clone(), credential);\n }\n return {\n name: scenario.name,\n status: \"passed\",\n responseStatus: response.status,\n };\n } catch (error) {\n return {\n name: scenario.name,\n status: \"failed\",\n error: error instanceof Error ? error.message : String(error),\n };\n } finally {\n await credential?.dispose?.();\n }\n}\n\n/** Runs the common API-key or OAuth resource-server regression matrix. */\nexport async function runAuthRegressionSuite(\n options: McpFnAuthRegressionOptions,\n): Promise<McpFnAuthScenarioResult[]> {\n const issue = (overrides: Partial<McpFnAuthCredentialRequest> = {}) =>\n options.provider.issue({\n kind: options.kind,\n scopes: options.requiredScopes,\n resource: options.resource,\n ...overrides,\n });\n const results: McpFnAuthScenarioResult[] = [];\n results.push(await runOne(\n options,\n { name: \"missing-credential\", kind: options.kind },\n async () => undefined,\n 401,\n ));\n results.push(await runOne(\n options,\n { name: \"invalid-credential\", kind: options.kind },\n async () => undefined,\n 401,\n ));\n results.push(await runOne(\n options,\n { name: \"valid-credential\", kind: options.kind },\n () => issue(),\n options.expectedAuthenticatedStatuses ?? [200, 201, 202, 204],\n ));\n\n const capabilities = options.provider.capabilities ?? {};\n if (capabilities.scopes && options.requiredScopes?.length) {\n results.push(await runOne(\n options,\n { name: \"insufficient-scope\", kind: options.kind },\n () => issue({ scopes: [] }),\n 403,\n ));\n }\n if (capabilities.expiration) {\n results.push(await runOne(\n options,\n { name: \"expired-credential\", kind: options.kind },\n () => issue({ expiresInSeconds: -60 }),\n 401,\n ));\n }\n if (capabilities.resourceBinding && options.resource) {\n results.push(await runOne(\n options,\n { name: \"missing-resource\", kind: options.kind },\n () => issue({ resource: undefined }),\n 401,\n ));\n }\n if (capabilities.resourceBinding && options.wrongResource) {\n results.push(await runOne(\n options,\n { name: \"wrong-resource\", kind: options.kind },\n () => issue({ resource: options.wrongResource }),\n 401,\n ));\n }\n if (capabilities.revocation && options.provider.revoke) {\n results.push(await runOne(\n options,\n { name: \"revoked-credential\", kind: options.kind },\n async () => {\n const credential = await issue();\n await options.provider.revoke?.(credential);\n return credential;\n },\n 401,\n ));\n }\n return results;\n}\n\nexport async function assertAuthRegressionSuite(\n options: McpFnAuthRegressionOptions,\n): Promise<McpFnAuthScenarioResult[]> {\n const results = await runAuthRegressionSuite(options);\n const failures = results.filter((result) => result.status === \"failed\");\n if (failures.length) {\n throw new McpFnAuthAssertionError(\n failures.map((failure) => `${failure.name}: ${failure.error}`).join(\"\\n\"),\n );\n }\n return results;\n}\n\nexport interface McpFnFetchAuthTargetOptions {\n url: string | URL;\n fetch?: typeof globalThis.fetch;\n requestInit?: RequestInit | ((scenario: McpFnAuthProbeScenario) => RequestInit);\n}\n\n/** Creates a protected MCP initialize probe suitable for local or deployed endpoints. */\nexport function createFetchAuthTarget(\n options: McpFnFetchAuthTargetOptions,\n): McpFnAuthTarget {\n const fetchImplementation = options.fetch ?? globalThis.fetch;\n if (!fetchImplementation) {\n throw new Error(\"A fetch implementation is required\");\n }\n return {\n async request(authHeaders, scenario) {\n const configured = typeof options.requestInit === \"function\"\n ? options.requestInit(scenario)\n : options.requestInit ?? {};\n const headers = new Headers(configured.headers);\n headers.set(\"accept\", \"application/json, text/event-stream\");\n headers.set(\"content-type\", \"application/json\");\n authHeaders.forEach((value, name) => headers.set(name, value));\n return fetchImplementation(options.url, {\n method: \"POST\",\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: `mcpfn-auth-${scenario.name}`,\n method: \"initialize\",\n params: {\n protocolVersion: \"2025-11-25\",\n capabilities: {},\n clientInfo: { name: \"mcpfn-auth-test\", version: \"1.0.0\" },\n },\n }),\n ...configured,\n headers,\n });\n },\n };\n}\n\nexport const MCPFN_OAUTH_EXTENSION_GRANTS = {\n jwtBearer: \"urn:ietf:params:oauth:grant-type:jwt-bearer\",\n deviceCode: \"urn:ietf:params:oauth:grant-type:device_code\",\n generic: \"urn:example:params:oauth:grant-type:extension\",\n} as const;\n\nexport interface McpFnOAuthClientMetadata extends Record<string, unknown> {\n client_id: string;\n client_name?: string;\n redirect_uris: string[];\n response_types: string[];\n grant_types: string[];\n token_endpoint_auth_method: string;\n}\n\nexport interface McpFnOAuthClientMetadataFixtureOptions {\n clientId: string;\n redirectUris: string[];\n clientName?: string;\n extraGrantTypes?: string[];\n extraMetadata?: Record<string, unknown>;\n}\n\nexport interface McpFnOAuthClientMetadataVariants {\n basic: McpFnOAuthClientMetadata;\n jwtBearerExtension: McpFnOAuthClientMetadata;\n deviceCodeExtension: McpFnOAuthClientMetadata;\n genericExtension: McpFnOAuthClientMetadata;\n}\n\nexport interface McpFnNamedOAuthHostFixture {\n id: \"chatgpt\" | \"claude\";\n name: string;\n redirectUris: string[];\n responseTypes: [\"code\"];\n grantTypes: string[];\n tokenEndpointAuthMethod: \"none\";\n}\n\n/** Host-shaped fixtures; applications still configure their registered production URLs. */\nexport const MCPFN_NAMED_OAUTH_HOST_FIXTURES = {\n chatgpt: {\n id: \"chatgpt\",\n name: \"ChatGPT connector\",\n redirectUris: [\"https://chatgpt.com/connector_platform_oauth_redirect\"],\n responseTypes: [\"code\"],\n grantTypes: [\"authorization_code\", \"refresh_token\"],\n tokenEndpointAuthMethod: \"none\",\n },\n claude: {\n id: \"claude\",\n name: \"Claude connector\",\n redirectUris: [\"https://claude.example.com/oauth/callback\"],\n responseTypes: [\"code\"],\n grantTypes: [\n \"authorization_code\",\n \"refresh_token\",\n MCPFN_OAUTH_EXTENSION_GRANTS.jwtBearer,\n ],\n tokenEndpointAuthMethod: \"none\",\n },\n} as const satisfies Record<string, McpFnNamedOAuthHostFixture>;\n\nexport function createOAuthClientMetadataFixture(\n options: McpFnOAuthClientMetadataFixtureOptions,\n): McpFnOAuthClientMetadata {\n return {\n ...options.extraMetadata,\n client_id: new URL(options.clientId).toString(),\n client_name: options.clientName ?? \"McpFn OAuth test client\",\n redirect_uris: [...new Set(options.redirectUris.map((uri) => new URL(uri).toString()))],\n response_types: [\"code\"],\n grant_types: [\n \"authorization_code\",\n \"refresh_token\",\n ...new Set(options.extraGrantTypes ?? []),\n ],\n token_endpoint_auth_method: \"none\",\n };\n}\n\nexport function createOAuthClientMetadataVariants(\n baseUrl: string | URL,\n redirectUri = new URL(\"/callback\", baseUrl).toString(),\n): McpFnOAuthClientMetadataVariants {\n const base = new URL(baseUrl);\n const fixture = (name: string, extraGrantTypes: string[] = []) =>\n createOAuthClientMetadataFixture({\n clientId: new URL(`/client-metadata/${name}`, base).toString(),\n redirectUris: [redirectUri],\n clientName: `McpFn ${name} client`,\n extraGrantTypes,\n });\n return {\n basic: fixture(\"basic\"),\n jwtBearerExtension: fixture(\"jwt-bearer-extension\", [MCPFN_OAUTH_EXTENSION_GRANTS.jwtBearer]),\n deviceCodeExtension: fixture(\"device-code-extension\", [MCPFN_OAUTH_EXTENSION_GRANTS.deviceCode]),\n genericExtension: fixture(\"generic-extension\", [MCPFN_OAUTH_EXTENSION_GRANTS.generic]),\n };\n}\n\n/**\n * Validates compatibility with authorization-code + PKCE without applying a\n * closed-world allowlist to unrelated grant types advertised by the client.\n */\nexport function assertAuthorizationCodeClientMetadata(\n metadata: McpFnOAuthClientMetadata,\n expectedClientId?: string,\n): McpFnOAuthClientMetadata {\n if (expectedClientId && metadata.client_id !== new URL(expectedClientId).toString()) {\n throw new McpFnAuthAssertionError(\"OAuth client metadata client_id does not match its document URL\");\n }\n if (!metadata.response_types.includes(\"code\")) {\n throw new McpFnAuthAssertionError(\"OAuth client metadata does not support response_type=code\");\n }\n if (!metadata.grant_types.includes(\"authorization_code\")) {\n throw new McpFnAuthAssertionError(\"OAuth client metadata does not support authorization_code\");\n }\n if (!metadata.redirect_uris.length) {\n throw new McpFnAuthAssertionError(\"OAuth client metadata must declare at least one redirect URI\");\n }\n return metadata;\n}\n","import { randomUUID } from \"node:crypto\";\nimport { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport type { AddressInfo } from \"node:net\";\n\nimport type { AuthInfo } from \"@modelcontextprotocol/sdk/server/auth/types.js\";\nimport { derivePkceS256Challenge, generatePkcePair } from \"@superfunctions/oauth-core\";\n\nimport {\n assertAuthorizationCodeClientMetadata,\n createOAuthClientMetadataVariants,\n type McpFnOAuthClientMetadataVariants,\n} from \"./auth-core.js\";\n\ninterface AuthorizationCodeRecord {\n clientId: string;\n redirectUri: string;\n codeChallenge: string;\n scopes: string[];\n resource?: string;\n expiresAt: number;\n used: boolean;\n}\n\ninterface AccessTokenRecord {\n clientId: string;\n scopes: string[];\n resource?: string;\n expiresAt: number;\n revoked: boolean;\n}\n\ninterface RefreshTokenRecord {\n clientId: string;\n scopes: string[];\n resource?: string;\n expiresAt: number;\n revoked: boolean;\n}\n\nexport interface McpFnMockOAuthServerOptions {\n issuer: string | URL;\n clientId?: string;\n redirectUris?: string[];\n scopesSupported?: string[];\n accessTokenLifetimeSeconds?: number;\n authorizationCodeLifetimeSeconds?: number;\n refreshTokenLifetimeSeconds?: number;\n clock?: () => number;\n}\n\nexport interface McpFnMockOAuthTokenSet {\n access_token: string;\n token_type: \"Bearer\";\n expires_in: number;\n refresh_token: string;\n scope: string;\n resource?: string;\n}\n\nexport interface McpFnPkcePair {\n verifier: string;\n challenge: string;\n method: \"S256\";\n}\n\nexport interface McpFnOAuthCallback {\n url: string;\n parameters: Record<string, string>;\n}\n\nexport function createPkcePair(): McpFnPkcePair {\n const pair = generatePkcePair(48);\n return {\n verifier: pair.codeVerifier,\n challenge: pair.codeChallenge,\n method: pair.codeChallengeMethod,\n };\n}\n\nfunction uniqueScopes(value: string | null | undefined): string[] {\n return [...new Set((value ?? \"\").split(/\\s+/).filter(Boolean))].sort();\n}\n\nfunction json(status: number, body: unknown): Response {\n return Response.json(body, {\n status,\n headers: { \"cache-control\": \"no-store\" },\n });\n}\n\nfunction oauthError(status: number, error: string, description: string): Response {\n return json(status, { error, error_description: description });\n}\n\nfunction escapeHtml(value: string): string {\n return value\n .replaceAll(\"&\", \"&\")\n .replaceAll('\"', \""\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\">\", \">\");\n}\n\nfunction formValue(form: URLSearchParams, name: string): string | undefined {\n const value = form.get(name);\n return value === null || value === \"\" ? undefined : value;\n}\n\nexport class McpFnMockOAuthAuthorizationServer {\n readonly issuer: URL;\n readonly clientId: string;\n readonly redirectUris: string[];\n readonly scopesSupported: string[];\n readonly clientMetadata: McpFnOAuthClientMetadataVariants;\n\n private readonly codes = new Map<string, AuthorizationCodeRecord>();\n private readonly accessTokens = new Map<string, AccessTokenRecord>();\n private readonly refreshTokens = new Map<string, RefreshTokenRecord>();\n private readonly callbacks: McpFnOAuthCallback[] = [];\n private readonly clock: () => number;\n private readonly accessTokenLifetimeSeconds: number;\n private readonly authorizationCodeLifetimeSeconds: number;\n private readonly refreshTokenLifetimeSeconds: number;\n\n constructor(options: McpFnMockOAuthServerOptions) {\n this.issuer = new URL(options.issuer);\n this.issuer.pathname = this.issuer.pathname.replace(/\\/?$/, \"/\");\n this.clientId = options.clientId ?? \"mcpfn-playwright\";\n this.redirectUris = options.redirectUris?.map((uri) => new URL(uri).toString()) ?? [\n new URL(\"callback\", this.issuer).toString(),\n ];\n this.scopesSupported = [...new Set(options.scopesSupported ?? [\"mcp:read\", \"mcp:write\"])].sort();\n this.clock = options.clock ?? Date.now;\n this.accessTokenLifetimeSeconds = options.accessTokenLifetimeSeconds ?? 300;\n this.authorizationCodeLifetimeSeconds = options.authorizationCodeLifetimeSeconds ?? 120;\n this.refreshTokenLifetimeSeconds = options.refreshTokenLifetimeSeconds ?? 3_600;\n this.clientMetadata = createOAuthClientMetadataVariants(\n this.issuer,\n this.redirectUris[0],\n );\n }\n\n get metadataUrl(): string {\n return new URL(\".well-known/oauth-authorization-server\", this.issuer).toString();\n }\n\n get authorizationEndpoint(): string {\n return new URL(\"authorize\", this.issuer).toString();\n }\n\n get tokenEndpoint(): string {\n return new URL(\"token\", this.issuer).toString();\n }\n\n get revocationEndpoint(): string {\n return new URL(\"revoke\", this.issuer).toString();\n }\n\n get callbackUrl(): string {\n return this.redirectUris[0];\n }\n\n clientMetadataUrl(\n variant: keyof McpFnOAuthClientMetadataVariants,\n ): string {\n return this.clientMetadata[variant].client_id;\n }\n\n authorizationUrl(input: {\n clientId?: string;\n redirectUri?: string;\n codeChallenge: string;\n state?: string;\n scopes?: string[];\n resource?: string;\n extraParameters?: Record<string, string>;\n }): string {\n const url = new URL(this.authorizationEndpoint);\n url.searchParams.set(\"response_type\", \"code\");\n url.searchParams.set(\"client_id\", input.clientId ?? this.clientId);\n url.searchParams.set(\"redirect_uri\", input.redirectUri ?? this.callbackUrl);\n url.searchParams.set(\"code_challenge\", input.codeChallenge);\n url.searchParams.set(\"code_challenge_method\", \"S256\");\n url.searchParams.set(\"scope\", (input.scopes ?? [\"mcp:read\"]).join(\" \"));\n if (input.state) url.searchParams.set(\"state\", input.state);\n if (input.resource) url.searchParams.set(\"resource\", input.resource);\n for (const [name, value] of Object.entries(input.extraParameters ?? {})) {\n url.searchParams.set(name, value);\n }\n return url.toString();\n }\n\n latestCallback(): McpFnOAuthCallback | undefined {\n return this.callbacks.at(-1);\n }\n\n expireAccessToken(token: string): void {\n const record = this.accessTokens.get(token);\n if (record) record.expiresAt = this.nowSeconds() - 1;\n }\n\n revokeToken(token: string): void {\n const access = this.accessTokens.get(token);\n if (access) access.revoked = true;\n const refresh = this.refreshTokens.get(token);\n if (refresh) refresh.revoked = true;\n }\n\n async verifyAccessToken(token: string): Promise<AuthInfo> {\n const record = this.accessTokens.get(token);\n if (!record || record.revoked || record.expiresAt <= this.nowSeconds()) {\n throw new Error(\"Invalid access token\");\n }\n return {\n token,\n clientId: record.clientId,\n scopes: record.scopes,\n expiresAt: record.expiresAt,\n ...(record.resource ? { resource: new URL(record.resource) } : {}),\n };\n }\n\n async handle(request: Request): Promise<Response> {\n const url = new URL(request.url);\n const path = url.pathname.replace(this.issuer.pathname.replace(/\\/$/, \"\"), \"\") || \"/\";\n if (request.method === \"GET\" && path === \"/.well-known/oauth-authorization-server\") {\n return json(200, {\n issuer: this.issuer.toString(),\n authorization_endpoint: this.authorizationEndpoint,\n token_endpoint: this.tokenEndpoint,\n revocation_endpoint: this.revocationEndpoint,\n response_types_supported: [\"code\"],\n grant_types_supported: [\"authorization_code\", \"refresh_token\"],\n code_challenge_methods_supported: [\"S256\"],\n token_endpoint_auth_methods_supported: [\"none\"],\n scopes_supported: this.scopesSupported,\n client_id_metadata_document_supported: true,\n });\n }\n\n if (request.method === \"GET\" && path.startsWith(\"/client-metadata/\")) {\n const metadata = Object.values(this.clientMetadata)\n .find((candidate) => new URL(candidate.client_id).pathname === url.pathname);\n return metadata ? json(200, metadata) : json(404, { error: \"not_found\" });\n }\n\n if (request.method === \"GET\" && path === \"/authorize\") {\n return this.authorize(url);\n }\n if (request.method === \"POST\" && path === \"/token\") {\n return this.token(await request.text());\n }\n if (request.method === \"POST\" && path === \"/revoke\") {\n return this.revoke(await request.text());\n }\n if (request.method === \"GET\" && path === \"/callback\") {\n const parameters = Object.fromEntries(url.searchParams);\n this.callbacks.push({ url: url.toString(), parameters });\n return new Response(\n `<!doctype html><html><body><main><h1>OAuth callback received</h1><pre>${escapeHtml(JSON.stringify(parameters, null, 2))}</pre></main></body></html>`,\n { headers: { \"content-type\": \"text/html; charset=utf-8\" } },\n );\n }\n return json(404, { error: \"not_found\" });\n }\n\n private nowSeconds(): number {\n return Math.floor(this.clock() / 1_000);\n }\n\n private resolveClient(clientId: string): { clientId: string; redirectUris: string[] } | undefined {\n if (clientId === this.clientId) {\n return { clientId, redirectUris: this.redirectUris };\n }\n const metadata = Object.values(this.clientMetadata)\n .find((candidate) => candidate.client_id === clientId);\n if (!metadata) return undefined;\n assertAuthorizationCodeClientMetadata(metadata, clientId);\n return { clientId, redirectUris: metadata.redirect_uris };\n }\n\n private authorize(url: URL): Response {\n const clientId = url.searchParams.get(\"client_id\") ?? \"\";\n const redirectUri = url.searchParams.get(\"redirect_uri\") ?? \"\";\n const client = this.resolveClient(clientId);\n if (!client) return oauthError(400, \"invalid_client\", \"Unknown OAuth client\");\n if (!client.redirectUris.includes(redirectUri)) {\n return oauthError(400, \"invalid_request\", \"redirect_uri is not registered\");\n }\n if (url.searchParams.get(\"response_type\") !== \"code\") {\n return this.authorizationRedirect(url, redirectUri, \"unsupported_response_type\");\n }\n const codeChallenge = url.searchParams.get(\"code_challenge\");\n if (!codeChallenge || url.searchParams.get(\"code_challenge_method\") !== \"S256\") {\n return this.authorizationRedirect(url, redirectUri, \"invalid_request\", \"PKCE S256 is required\");\n }\n const requestedScopes = uniqueScopes(url.searchParams.get(\"scope\"));\n if (requestedScopes.some((scope) => !this.scopesSupported.includes(scope))) {\n return this.authorizationRedirect(url, redirectUri, \"invalid_scope\");\n }\n const decision = url.searchParams.get(\"decision\");\n if (!decision) {\n const hidden = [...url.searchParams]\n .filter(([name]) => name !== \"decision\")\n .map(([name, value]) => `<input type=\"hidden\" name=\"${escapeHtml(name)}\" value=\"${escapeHtml(value)}\">`)\n .join(\"\");\n return new Response(\n `<!doctype html><html><body><main><h1>Authorize MCP client</h1><p>${escapeHtml(clientId)}</p><form method=\"get\" action=\"${escapeHtml(this.authorizationEndpoint)}\">${hidden}<button name=\"decision\" value=\"approve\">Approve</button><button name=\"decision\" value=\"deny\">Deny</button></form></main></body></html>`,\n { headers: { \"content-type\": \"text/html; charset=utf-8\", \"cache-control\": \"no-store\" } },\n );\n }\n if (decision === \"deny\") {\n return this.authorizationRedirect(url, redirectUri, \"access_denied\");\n }\n if (decision !== \"approve\") {\n return oauthError(400, \"invalid_request\", \"Unknown authorization decision\");\n }\n const code = `mcpfn_code_${randomUUID()}`;\n this.codes.set(code, {\n clientId,\n redirectUri,\n codeChallenge,\n scopes: requestedScopes,\n resource: url.searchParams.get(\"resource\") ?? undefined,\n expiresAt: this.nowSeconds() + this.authorizationCodeLifetimeSeconds,\n used: false,\n });\n const callback = new URL(redirectUri);\n callback.searchParams.set(\"code\", code);\n const state = url.searchParams.get(\"state\");\n if (state) callback.searchParams.set(\"state\", state);\n return Response.redirect(callback, 302);\n }\n\n private authorizationRedirect(\n requestUrl: URL,\n redirectUri: string,\n error: string,\n description?: string,\n ): Response {\n const callback = new URL(redirectUri);\n callback.searchParams.set(\"error\", error);\n if (description) callback.searchParams.set(\"error_description\", description);\n const state = requestUrl.searchParams.get(\"state\");\n if (state) callback.searchParams.set(\"state\", state);\n return Response.redirect(callback, 302);\n }\n\n private token(source: string): Response {\n const form = new URLSearchParams(source);\n const grantType = formValue(form, \"grant_type\");\n if (grantType === \"authorization_code\") return this.exchangeAuthorizationCode(form);\n if (grantType === \"refresh_token\") return this.exchangeRefreshToken(form);\n return oauthError(400, \"unsupported_grant_type\", \"The grant type is not supported\");\n }\n\n private exchangeAuthorizationCode(form: URLSearchParams): Response {\n const code = formValue(form, \"code\");\n const record = code ? this.codes.get(code) : undefined;\n if (!record || record.used || record.expiresAt <= this.nowSeconds()) {\n return oauthError(400, \"invalid_grant\", \"Authorization code is invalid or expired\");\n }\n if (\n formValue(form, \"client_id\") !== record.clientId ||\n formValue(form, \"redirect_uri\") !== record.redirectUri\n ) {\n return oauthError(400, \"invalid_grant\", \"Authorization code binding does not match\");\n }\n const verifier = formValue(form, \"code_verifier\");\n const challenge = verifier ? derivePkceS256Challenge(verifier) : undefined;\n if (challenge !== record.codeChallenge) {\n return oauthError(400, \"invalid_grant\", \"PKCE verification failed\");\n }\n record.used = true;\n return json(200, this.issueTokenSet(record));\n }\n\n private exchangeRefreshToken(form: URLSearchParams): Response {\n const refreshToken = formValue(form, \"refresh_token\");\n const record = refreshToken ? this.refreshTokens.get(refreshToken) : undefined;\n if (!record || record.revoked || record.expiresAt <= this.nowSeconds()) {\n return oauthError(400, \"invalid_grant\", \"Refresh token is invalid or expired\");\n }\n if (formValue(form, \"client_id\") !== record.clientId) {\n return oauthError(400, \"invalid_grant\", \"Refresh token client binding does not match\");\n }\n const requestedScopes = form.has(\"scope\")\n ? uniqueScopes(form.get(\"scope\"))\n : record.scopes;\n if (requestedScopes.some((scope) => !record.scopes.includes(scope))) {\n return oauthError(400, \"invalid_scope\", \"Refresh cannot increase granted scopes\");\n }\n record.revoked = true;\n return json(200, this.issueTokenSet({ ...record, scopes: requestedScopes }));\n }\n\n private issueTokenSet(\n input: Pick<AccessTokenRecord, \"clientId\" | \"scopes\" | \"resource\">,\n ): McpFnMockOAuthTokenSet {\n const accessToken = `mcpfn_access_${randomUUID()}`;\n const refreshToken = `mcpfn_refresh_${randomUUID()}`;\n this.accessTokens.set(accessToken, {\n ...input,\n expiresAt: this.nowSeconds() + this.accessTokenLifetimeSeconds,\n revoked: false,\n });\n this.refreshTokens.set(refreshToken, {\n ...input,\n expiresAt: this.nowSeconds() + this.refreshTokenLifetimeSeconds,\n revoked: false,\n });\n return {\n access_token: accessToken,\n token_type: \"Bearer\",\n expires_in: this.accessTokenLifetimeSeconds,\n refresh_token: refreshToken,\n scope: input.scopes.join(\" \"),\n ...(input.resource ? { resource: input.resource } : {}),\n };\n }\n\n private revoke(source: string): Response {\n const token = new URLSearchParams(source).get(\"token\");\n if (token) this.revokeToken(token);\n return new Response(null, { status: 200 });\n }\n}\n\nexport interface McpFnStartedMockOAuthServer {\n origin: string;\n oauth: McpFnMockOAuthAuthorizationServer;\n close(): Promise<void>;\n}\n\nexport interface McpFnStartMockOAuthServerOptions\n extends Omit<McpFnMockOAuthServerOptions, \"issuer\"> {\n hostname?: string;\n port?: number;\n /** Optional same-origin route used to compose a protected MCP fixture. */\n handle?(\n request: Request,\n oauth: McpFnMockOAuthAuthorizationServer,\n ): Promise<Response | undefined> | Response | undefined;\n}\n\nasync function toRequest(req: IncomingMessage, origin: string): Promise<Request> {\n const chunks: Buffer[] = [];\n for await (const chunk of req) chunks.push(Buffer.from(chunk));\n const headers = new Headers();\n for (const [name, value] of Object.entries(req.headers)) {\n if (Array.isArray(value)) {\n for (const entry of value) headers.append(name, entry);\n } else if (value !== undefined) {\n headers.set(name, value);\n }\n }\n const body = chunks.length ? Buffer.concat(chunks) : undefined;\n const init: RequestInit & { duplex?: \"half\" } = {\n method: req.method,\n headers,\n ...(body ? { body, duplex: \"half\" } : {}),\n };\n return new Request(new URL(req.url ?? \"/\", origin), init);\n}\n\nasync function writeResponse(res: ServerResponse, response: Response): Promise<void> {\n res.statusCode = response.status;\n response.headers.forEach((value, name) => res.setHeader(name, value));\n res.end(Buffer.from(await response.arrayBuffer()));\n}\n\nexport async function startMockOAuthAuthorizationServer(\n options: McpFnStartMockOAuthServerOptions = {},\n): Promise<McpFnStartedMockOAuthServer> {\n let oauth: McpFnMockOAuthAuthorizationServer | undefined;\n let origin = \"\";\n const server = createServer(async (req, res) => {\n try {\n if (!oauth) throw new Error(\"Mock OAuth server is not initialized\");\n const request = await toRequest(req, origin);\n const custom = await options.handle?.(request.clone(), oauth);\n await writeResponse(res, custom ?? await oauth.handle(request));\n } catch {\n res.statusCode = 500;\n res.setHeader(\"content-type\", \"application/json\");\n res.end(JSON.stringify({\n error: \"server_error\",\n error_description: \"Internal Server Error\",\n }));\n }\n });\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject);\n server.listen(options.port ?? 0, options.hostname ?? \"127.0.0.1\", () => {\n server.off(\"error\", reject);\n resolve();\n });\n });\n const address = server.address() as AddressInfo;\n origin = `http://${address.address.includes(\":\") ? `[${address.address}]` : address.address}:${address.port}`;\n oauth = new McpFnMockOAuthAuthorizationServer({ ...options, issuer: origin });\n return {\n origin,\n oauth,\n close: () => new Promise<void>((resolve, reject) => {\n server.close((error) => error ? reject(error) : resolve());\n }),\n };\n}\n","import {\n createMcpFnClient,\n customTarget,\n type McpFnClient,\n type McpFnClientEventSink,\n type McpFnClientMediatedHandlers,\n type McpFnDiagnosticSink,\n type McpFnTarget,\n} from \"@mcpfn/client\";\nimport { InMemoryTransport } from \"@modelcontextprotocol/sdk/inMemory.js\";\nimport type { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport type { RequestOptions } from \"@modelcontextprotocol/sdk/shared/protocol.js\";\nimport type {\n CallToolResult,\n ClientCapabilities,\n CompleteRequest,\n CompleteResult,\n CreateTaskResult,\n GetPromptResult,\n Implementation,\n ListTasksResult,\n Prompt,\n ReadResourceResult,\n Resource,\n ResourceTemplate,\n Task,\n Tool,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { McpFnServer } from \"@mcpfn/core\";\n\nexport interface McpFnTestClientOptions {\n capabilities?: ClientCapabilities;\n handlers?: McpFnClientMediatedHandlers;\n events?: McpFnClientEventSink;\n /** Install roots, sampling, elicitation, or notification handlers before initialize. */\n configure?(client: Client): void | Promise<void>;\n diagnostics?: McpFnDiagnosticSink;\n}\n\nexport class McpFnTestClient<TContext = undefined> {\n readonly session: McpFnClient;\n\n private constructor(session: McpFnClient) {\n this.session = session;\n }\n\n get client(): Client {\n return this.session.protocol;\n }\n\n static async connect<TContext>(\n server: McpFnServer<TContext>,\n info = { name: \"mcpfn-test-client\", version: \"1.0.0\" },\n options: McpFnTestClientOptions = {},\n ): Promise<McpFnTestClient<TContext>> {\n const serverName = (server as McpFnServer<TContext> & { info?: { name?: string } })\n .info?.name ?? \"mcpfn-server\";\n return this.connectTarget<TContext>(customTarget({\n kind: \"in-memory\",\n descriptor: { server: serverName },\n open: async () => {\n const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();\n await server.connect(serverTransport);\n return { transport: clientTransport, close: () => server.close() };\n },\n }), info, options);\n }\n\n static async connectTarget<TContext = undefined>(\n target: McpFnTarget,\n info?: Implementation,\n options: McpFnTestClientOptions = {},\n ): Promise<McpFnTestClient<TContext>> {\n const session = createMcpFnClient({\n target,\n info: info ?? { name: \"mcpfn-test-client\", version: \"1.0.0\" },\n capabilities: options.capabilities,\n handlers: options.handlers,\n events: options.events,\n configure: options.configure,\n diagnostics: options.diagnostics,\n });\n try {\n await session.connect();\n return new McpFnTestClient<TContext>(session);\n } catch (error) {\n await session.close(true).catch(() => undefined);\n throw error;\n }\n }\n\n listTools(options?: RequestOptions): Promise<Tool[]> { return this.session.tools.listAll(options); }\n callTool(\n name: string,\n args: Record<string, unknown> = {},\n options?: RequestOptions,\n ): Promise<CallToolResult> {\n return this.session.tools.call(name, args, options);\n }\n createToolTask(\n name: string,\n args: Record<string, unknown> = {},\n task: { ttl?: number } = {},\n options?: RequestOptions,\n ): Promise<CreateTaskResult> {\n return this.session.tools.createTask(name, args, task, options);\n }\n getTask(taskId: string, options?: RequestOptions): Promise<Task> {\n return this.session.tasks.get(taskId, options);\n }\n getTaskResult(taskId: string, options?: RequestOptions): Promise<CallToolResult> {\n return this.session.tasks.result(taskId, options);\n }\n listTasks(cursor?: string, options?: RequestOptions): Promise<ListTasksResult> {\n return this.session.tasks.list(cursor, options);\n }\n cancelTask(taskId: string, options?: RequestOptions): Promise<Task> {\n return this.session.tasks.cancel(taskId, options);\n }\n listResources(options?: RequestOptions): Promise<Resource[]> {\n return this.session.resources.listAll(options);\n }\n listResourceTemplates(options?: RequestOptions): Promise<ResourceTemplate[]> {\n return this.session.resources.listTemplatesAll(options);\n }\n readResource(uri: string, options?: RequestOptions): Promise<ReadResourceResult> {\n return this.session.resources.read(uri, options);\n }\n subscribeResource(uri: string, options?: RequestOptions): Promise<void> {\n return this.session.resources.subscribe(uri, options);\n }\n unsubscribeResource(uri: string, options?: RequestOptions): Promise<void> {\n return this.session.resources.unsubscribe(uri, options);\n }\n listPrompts(options?: RequestOptions): Promise<Prompt[]> {\n return this.session.prompts.listAll(options);\n }\n getPrompt(\n name: string,\n args?: Record<string, string>,\n options?: RequestOptions,\n ): Promise<GetPromptResult> {\n return this.session.prompts.get(name, args, options);\n }\n complete(params: CompleteRequest[\"params\"], options?: RequestOptions): Promise<CompleteResult> {\n return this.session.prompts.complete(params, options);\n }\n close(): Promise<void> { return this.session.close(); }\n}\n","import { spawn } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport {\n createServer,\n request as httpRequest,\n type IncomingHttpHeaders,\n} from \"node:http\";\nimport { request as httpsRequest } from \"node:https\";\nimport type { Socket } from \"node:net\";\nimport path from \"node:path\";\n\nexport const OFFICIAL_CONFORMANCE_VERSION = \"0.1.16\";\n\nexport interface OfficialConformanceOptions {\n url: string;\n suite?: \"active\" | \"all\" | \"pending\";\n scenario?: string;\n expectedFailures?: string;\n outputDir?: string;\n specVersion?: string;\n verbose?: boolean;\n cwd?: string;\n stdio?: \"inherit\" | \"pipe\";\n}\n\nexport interface OfficialConformanceResult {\n exitCode: number;\n stdout: string;\n stderr: string;\n}\n\nexport interface AuthenticatedConformanceProxy {\n /** Loopback URL to pass to the official conformance runner. */\n url: string;\n close(): Promise<void>;\n}\n\nexport interface AuthenticatedConformanceProxyOptions {\n /** Fixed loopback MCP URL. Requests cannot select a different origin or path. */\n url: string;\n /** Headers injected into requests using the proxy's own authority. Values are never logged. */\n headers: HeadersInit;\n}\n\nexport interface AuthenticatedOfficialConformanceOptions extends OfficialConformanceOptions {\n headers: HeadersInit;\n}\n\n/**\n * Start a loopback-only streaming proxy for runners that cannot send auth\n * headers. Authenticated requests use one fixed upstream authority and path.\n * Host-manipulation probes are forwarded without injected credentials.\n */\nexport async function createAuthenticatedConformanceProxy(\n options: AuthenticatedConformanceProxyOptions,\n): Promise<AuthenticatedConformanceProxy> {\n const upstream = new URL(options.url);\n if (![\"http:\", \"https:\"].includes(upstream.protocol)) {\n throw new TypeError(\n \"Authenticated conformance upstream must use HTTP or HTTPS\",\n );\n }\n if (upstream.username || upstream.password || upstream.hash) {\n throw new TypeError(\n \"Authenticated conformance upstream must not contain userinfo or a fragment\",\n );\n }\n const hostname = normalizeLoopbackHostname(upstream.hostname);\n if (!hostname) {\n throw new TypeError(\n \"Authenticated conformance upstream must use a literal loopback address\",\n );\n }\n const protocol = upstream.protocol === \"https:\" ? \"https:\" : \"http:\";\n const port = upstream.port === \"\" ? undefined : Number(upstream.port);\n const requestPath = `${upstream.pathname}${upstream.search}`;\n const injected = new Headers(options.headers);\n const activeRequests = new Set<ReturnType<typeof httpRequest>>();\n const activeSockets = new Set<Socket>();\n let proxyAuthority: string | undefined;\n const server = createServer((incoming, outgoing) => {\n if (!incoming.url?.startsWith(\"/\")) {\n outgoing.writeHead(400).end();\n return;\n }\n const headers: IncomingHttpHeaders = { ...incoming.headers };\n delete headers.connection;\n const usesProxyAuthority = incoming.headers.host === proxyAuthority;\n injected.forEach((value, name) => {\n const normalizedName = name.toLowerCase();\n delete headers[normalizedName];\n if (usesProxyAuthority) headers[normalizedName] = value;\n });\n // Authenticated traffic is pinned to the upstream Host. Host-manipulation\n // probes retain their hostile value, but never receive injected credentials.\n if (usesProxyAuthority) headers.host = upstream.host;\n const transport = protocol === \"https:\" ? httpsRequest : httpRequest;\n const proxied = transport(\n {\n protocol,\n hostname,\n port,\n path: requestPath,\n method: incoming.method,\n headers,\n },\n (response) => {\n outgoing.writeHead(response.statusCode ?? 502, response.headers);\n response.pipe(outgoing);\n },\n );\n activeRequests.add(proxied);\n proxied.once(\"close\", () => activeRequests.delete(proxied));\n proxied.once(\"error\", () => {\n if (!outgoing.headersSent) outgoing.writeHead(502);\n outgoing.end();\n });\n incoming.once(\"aborted\", () => proxied.destroy());\n incoming.pipe(proxied);\n });\n server.on(\"connection\", (socket) => {\n activeSockets.add(socket);\n socket.once(\"close\", () => activeSockets.delete(socket));\n });\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject);\n server.listen(0, \"127.0.0.1\", () => {\n server.off(\"error\", reject);\n resolve();\n });\n });\n const address = server.address();\n if (!address || typeof address === \"string\") {\n await new Promise<void>((resolve) => server.close(() => resolve()));\n throw new Error(\"Authenticated conformance proxy did not bind a TCP port\");\n }\n const url = new URL(\n upstream.pathname + upstream.search,\n `http://127.0.0.1:${address.port}`,\n );\n proxyAuthority = url.host;\n return {\n url: url.toString(),\n close: async () => {\n for (const request of activeRequests) request.destroy();\n for (const socket of activeSockets) socket.destroy();\n if (!server.listening) return;\n await new Promise<void>((resolve, reject) => {\n server.close((error) => (error ? reject(error) : resolve()));\n });\n },\n };\n}\n\nfunction normalizeLoopbackHostname(\n hostname: string,\n): \"127.0.0.1\" | \"::1\" | undefined {\n if (hostname === \"127.0.0.1\") return \"127.0.0.1\";\n if (hostname === \"[::1]\") return \"::1\";\n return undefined;\n}\n\nfunction npxInvocation(args: string[]): { command: string; args: string[] } {\n if (process.platform !== \"win32\") return { command: \"npx\", args };\n const npmExecPath = process.env.npm_execpath;\n const candidates = [\n npmExecPath ? path.join(path.dirname(npmExecPath), \"npx-cli.js\") : undefined,\n path.resolve(path.dirname(process.execPath), \"node_modules/npm/bin/npx-cli.js\"),\n path.resolve(path.dirname(process.execPath), \"../lib/node_modules/npm/bin/npx-cli.js\"),\n ].filter((candidate): candidate is string => Boolean(candidate));\n const npxCli = candidates.find((candidate) => existsSync(candidate));\n if (!npxCli) {\n throw new Error(\"Unable to locate npm's npx-cli.js for the official MCP conformance runner\");\n }\n return { command: process.execPath, args: [npxCli, ...args] };\n}\n\nexport function buildOfficialConformanceArgs(\n options: OfficialConformanceOptions,\n): string[] {\n const args = [\n \"--yes\",\n `@modelcontextprotocol/conformance@${OFFICIAL_CONFORMANCE_VERSION}`,\n \"server\",\n \"--url\",\n options.url,\n ];\n if (options.suite) args.push(\"--suite\", options.suite);\n if (options.scenario) args.push(\"--scenario\", options.scenario);\n if (options.expectedFailures) {\n args.push(\"--expected-failures\", options.expectedFailures);\n }\n if (options.outputDir) args.push(\"--output-dir\", options.outputDir);\n if (options.specVersion) args.push(\"--spec-version\", options.specVersion);\n if (options.verbose) args.push(\"--verbose\");\n return args;\n}\n\nexport async function runOfficialConformance(\n options: OfficialConformanceOptions,\n): Promise<OfficialConformanceResult> {\n const nodeMajor = Number.parseInt(process.versions.node.split(\".\")[0] ?? \"0\", 10);\n if (nodeMajor < 22) {\n throw new Error(\n `Official MCP conformance ${OFFICIAL_CONFORMANCE_VERSION} requires Node.js 22 or newer; current runtime is ${process.versions.node}`,\n );\n }\n const args = buildOfficialConformanceArgs(options);\n const invocation = npxInvocation(args);\n\n return await new Promise<OfficialConformanceResult>((resolve, reject) => {\n const child = spawn(invocation.command, invocation.args, {\n cwd: options.cwd,\n env: {\n ...process.env,\n PATH: [path.dirname(process.execPath), process.env.PATH]\n .filter(Boolean)\n .join(path.delimiter),\n },\n stdio: options.stdio === \"inherit\" ? \"inherit\" : \"pipe\",\n });\n let stdout = \"\";\n let stderr = \"\";\n child.stdout?.on(\"data\", (chunk) => {\n stdout += chunk.toString();\n });\n child.stderr?.on(\"data\", (chunk) => {\n stderr += chunk.toString();\n });\n child.once(\"error\", reject);\n child.once(\"close\", (code) => {\n resolve({ exitCode: code ?? 1, stdout, stderr });\n });\n });\n}\n\n/** Run the pinned official suite against an authenticated MCP endpoint. */\nexport async function runAuthenticatedOfficialConformance(\n options: AuthenticatedOfficialConformanceOptions,\n): Promise<OfficialConformanceResult> {\n const { headers, ...conformance } = options;\n const proxy = await createAuthenticatedConformanceProxy({\n url: conformance.url,\n headers,\n });\n try {\n return await runOfficialConformance({ ...conformance, url: proxy.url });\n } finally {\n await proxy.close();\n }\n}\n","import {\n MCP_APP_EXTENSION_ID,\n type McpFnManifest,\n} from \"@mcpfn/core\";\n\nexport type McpFnServerFeature =\n | \"tools\"\n | \"resources\"\n | \"prompts\"\n | \"completions\"\n | \"tasks\"\n | \"logging\";\n\nexport interface McpFnHostProfile {\n id: string;\n name: string;\n protocolVersions: string[];\n serverFeatures: McpFnServerFeature[];\n clientFeatures?: {\n sampling?: boolean;\n elicitation?: Array<\"form\" | \"url\">;\n roots?: boolean;\n };\n extensions?: string[];\n}\n\nexport interface McpFnHostCompatibilityIssue {\n severity: \"incompatible\" | \"degraded\";\n code: string;\n path: string;\n message: string;\n}\n\nexport interface McpFnHostCompatibilityResult {\n status: \"compatible\" | \"degraded\" | \"incompatible\";\n compatible: boolean;\n issues: McpFnHostCompatibilityIssue[];\n}\n\nexport const MCPFN_HOST_PROFILES = {\n toolsOnly: {\n id: \"mcpfn/tools-only\",\n name: \"Tools-only MCP host\",\n protocolVersions: [\"2025-03-26\", \"2025-06-18\", \"2025-11-25\"],\n serverFeatures: [\"tools\"],\n },\n fullProtocol: {\n id: \"mcpfn/full-protocol\",\n name: \"Full protocol MCP host\",\n protocolVersions: [\"2025-03-26\", \"2025-06-18\", \"2025-11-25\"],\n serverFeatures: [\"tools\", \"resources\", \"prompts\", \"completions\", \"tasks\", \"logging\"],\n clientFeatures: { sampling: true, elicitation: [\"form\", \"url\"], roots: true },\n },\n mcpApps: {\n id: \"mcpfn/mcp-apps\",\n name: \"Full protocol host with MCP Apps\",\n protocolVersions: [\"2025-11-25\"],\n serverFeatures: [\"tools\", \"resources\", \"prompts\", \"completions\", \"tasks\", \"logging\"],\n clientFeatures: { sampling: true, elicitation: [\"form\", \"url\"], roots: true },\n extensions: [MCP_APP_EXTENSION_ID],\n },\n} as const satisfies Record<string, McpFnHostProfile>;\n\nexport function checkHostCompatibility(\n manifest: McpFnManifest,\n profile: McpFnHostProfile,\n): McpFnHostCompatibilityResult {\n const issues: McpFnHostCompatibilityIssue[] = [];\n if (\n manifest.protocolVersions?.length &&\n !manifest.protocolVersions.some((version) => profile.protocolVersions.includes(version))\n ) {\n issues.push({\n severity: \"incompatible\",\n code: \"protocol-version-mismatch\",\n path: \"protocolVersions\",\n message: `${profile.name} and ${manifest.server.name} have no protocol version in common`,\n });\n }\n\n const supportedServerFeatures = new Set(profile.serverFeatures);\n for (const feature of Object.keys(manifest.capabilities ?? {})) {\n if (\n feature === \"experimental\" ||\n supportedServerFeatures.has(feature as McpFnServerFeature)\n ) continue;\n issues.push({\n severity: \"degraded\",\n code: \"server-feature-unavailable\",\n path: `capabilities.${feature}`,\n message: `${profile.name} will not expose the server's ${feature} feature`,\n });\n }\n\n const required = manifest.clientRequirements;\n if (required?.sampling && !profile.clientFeatures?.sampling) {\n issues.push({\n severity: \"incompatible\",\n code: \"sampling-required\",\n path: \"clientRequirements.sampling\",\n message: `${manifest.server.name} requires client sampling`,\n });\n }\n if (required?.roots && !profile.clientFeatures?.roots) {\n issues.push({\n severity: \"incompatible\",\n code: \"roots-required\",\n path: \"clientRequirements.roots\",\n message: `${manifest.server.name} requires client roots`,\n });\n }\n for (const mode of required?.elicitation ?? []) {\n if (!profile.clientFeatures?.elicitation?.includes(mode)) {\n issues.push({\n severity: \"incompatible\",\n code: \"elicitation-required\",\n path: `clientRequirements.elicitation.${mode}`,\n message: `${manifest.server.name} requires ${mode} elicitation`,\n });\n }\n }\n\n const extensions = new Set(profile.extensions ?? []);\n for (const [extension, configuration] of Object.entries(manifest.extensions ?? {})) {\n if (extensions.has(extension)) continue;\n const requiredExtension =\n configuration && typeof configuration === \"object\" &&\n (configuration as Record<string, unknown>).required === true;\n issues.push({\n severity: requiredExtension ? \"incompatible\" : \"degraded\",\n code: \"extension-unavailable\",\n path: `extensions.${extension}`,\n message: `${profile.name} does not support ${extension}`,\n });\n }\n\n if (!extensions.has(MCP_APP_EXTENSION_ID)) {\n for (const tool of manifest.tools) {\n const ui = tool.metadata?.ui as { visibility?: string[] } | undefined;\n if (ui?.visibility?.length && !ui.visibility.includes(\"model\")) {\n issues.push({\n severity: \"incompatible\",\n code: \"app-only-tool-unavailable\",\n path: `tools.${tool.name}.metadata.ui.visibility`,\n message: `${tool.name} is app-only but ${profile.name} does not support MCP Apps`,\n });\n }\n }\n }\n\n issues.sort((left, right) => {\n if (left.path !== right.path) return left.path < right.path ? -1 : 1;\n if (left.code < right.code) return -1;\n if (left.code > right.code) return 1;\n return 0;\n });\n let status: McpFnHostCompatibilityResult[\"status\"] = \"compatible\";\n if (issues.some((issue) => issue.severity === \"incompatible\")) {\n status = \"incompatible\";\n } else if (issues.length > 0) {\n status = \"degraded\";\n }\n return { status, compatible: status !== \"incompatible\", issues };\n}\n","import type {\n CallToolResult,\n CreateTaskResult,\n GetPromptResult,\n ListTasksResult,\n ReadResourceResult,\n Task,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { McpFnClientEvent, McpFnClientEventKind } from \"@mcpfn/client\";\nimport { redactOAuthValue } from \"@superfunctions/oauth-core\";\n\nimport { McpFnAssertionError, assertStructuredTextParity, stableJson } from \"./assertions.js\";\nimport type { McpFnTestClient } from \"./client.js\";\n\nexport type McpFnScenarioSideEffect = \"none\" | \"idempotent\" | \"non-idempotent\";\n\nexport interface McpFnScenarioBase {\n formatVersion?: 1;\n name: string;\n /** Defaults to the runner timeout. */\n timeoutMs?: number;\n sideEffect?: McpFnScenarioSideEffect;\n status?: \"complete\" | \"incomplete\";\n incompleteReason?: string;\n /** Environment-backed placeholders used by this scenario, never their values. */\n variables?: string[];\n}\n\nexport interface McpFnToolScenario extends McpFnScenarioBase {\n kind?: \"tools.call\";\n tool: string;\n arguments?: Record<string, unknown>;\n expect?: {\n isError?: boolean;\n structuredContent?: unknown;\n structuredTextParity?: boolean;\n };\n verify?(result: CallToolResult): void | Promise<void>;\n}\n\nexport interface McpFnInventoryScenario extends McpFnScenarioBase {\n kind: \"tools.list\" | \"resources.list\" | \"resources.templates.list\" | \"prompts.list\";\n expectNames?: string[];\n}\n\nexport interface McpFnResourceScenario extends McpFnScenarioBase {\n kind: \"resources.read\" | \"resources.subscribe\" | \"resources.unsubscribe\";\n uri: string;\n expect?: unknown;\n}\n\nexport interface McpFnPromptScenario extends McpFnScenarioBase {\n kind: \"prompts.get\";\n prompt: string;\n arguments?: Record<string, string>;\n expect?: unknown;\n}\n\nexport interface McpFnInitializeScenario extends McpFnScenarioBase {\n kind: \"initialize\";\n expectCapabilities?: Record<string, unknown>;\n}\n\nexport interface McpFnCreateTaskScenario extends McpFnScenarioBase {\n kind: \"tools.call:task\";\n tool: string;\n arguments?: Record<string, unknown>;\n task?: { ttl?: number };\n expect?: unknown;\n}\n\nexport interface McpFnTaskScenario extends McpFnScenarioBase {\n kind: \"tasks.get\" | \"tasks.result\" | \"tasks.cancel\" | \"tasks.list\";\n taskId?: string;\n cursor?: string;\n expect?: unknown;\n}\n\nexport interface McpFnEventScenario extends McpFnScenarioBase {\n kind: \"events.expect\";\n event: McpFnClientEventKind;\n minimum?: number;\n expectPayload?: unknown;\n}\n\nexport interface McpFnAuthScenario extends McpFnScenarioBase {\n kind: \"auth.assert\";\n phase: string;\n expect: {\n outcome: \"allowed\" | \"denied\";\n code?: string;\n };\n input?: Record<string, unknown>;\n}\n\nexport type McpFnScenario =\n | McpFnToolScenario\n | McpFnInventoryScenario\n | McpFnResourceScenario\n | McpFnPromptScenario\n | McpFnInitializeScenario\n | McpFnCreateTaskScenario\n | McpFnTaskScenario\n | McpFnEventScenario\n | McpFnAuthScenario;\n\nexport interface McpFnScenarioArtifact {\n formatVersion: 1;\n kind: \"mcpfn.scenarios\";\n status: \"complete\" | \"incomplete\";\n scenarios: McpFnScenario[];\n variables?: string[];\n incompleteReason?: string;\n}\n\nexport type McpFnRecordedOperation =\n | { kind: \"tools.call\"; name: string; arguments?: Record<string, unknown> }\n | { kind: \"tools.call:task\"; name: string; arguments?: Record<string, unknown>; task?: { ttl?: number } }\n | { kind: \"resources.read\"; uri: string }\n | { kind: \"resources.subscribe\"; uri: string }\n | { kind: \"resources.unsubscribe\"; uri: string }\n | { kind: \"prompts.get\"; name: string; arguments?: Record<string, string> }\n | { kind: \"tasks.get\"; taskId: string }\n | { kind: \"tasks.result\"; taskId: string }\n | { kind: \"tasks.cancel\"; taskId: string }\n | { kind: \"tasks.list\"; cursor?: string };\n\nexport type McpFnRecordedOperationResult =\n | CallToolResult\n | ReadResourceResult\n | GetPromptResult\n | CreateTaskResult\n | Task\n | ListTasksResult\n | void;\n\nexport interface McpFnScenarioResult {\n formatVersion: 1;\n name: string;\n operation: string;\n tool?: string;\n status: \"passed\" | \"failed\" | \"incomplete\";\n sideEffect: McpFnScenarioSideEffect;\n durationMs: number;\n error?: string;\n /** Observed client events discarded while this scenario was running. */\n droppedObservedEvents?: number;\n}\n\nexport interface McpFnScenarioReport {\n formatVersion: 1;\n kind: \"mcpfn.scenario-report\";\n status: \"complete\" | \"incomplete\";\n manifestHash?: string;\n total: number;\n passed: number;\n failed: number;\n incomplete: number;\n droppedResults: number;\n droppedObservedEvents: number;\n incompleteReason?: string;\n results: McpFnScenarioResult[];\n}\n\n/** Convert an observed production-client operation into the shared runner contract. */\nexport function createMcpFnScenario(\n name: string,\n operation: McpFnRecordedOperation,\n result: McpFnRecordedOperationResult,\n): McpFnScenario {\n switch (operation.kind) {\n case \"tools.call\":\n return createToolCallScenario(name, operation, result as CallToolResult);\n case \"tools.call:task\":\n return createToolTaskScenario(name, operation);\n case \"resources.read\":\n return createResourceReadScenario(name, operation, result);\n case \"resources.subscribe\":\n case \"resources.unsubscribe\":\n return createResourceLifecycleScenario(name, operation);\n case \"tasks.get\":\n case \"tasks.cancel\":\n return createTaskLifecycleScenario(name, operation);\n case \"tasks.result\":\n return createTaskResultScenario(name, operation, result);\n case \"tasks.list\":\n return createTaskListScenario(name, operation);\n case \"prompts.get\":\n return createPromptScenario(name, operation, result);\n }\n}\n\nfunction scenarioBase(name: string, sideEffect: McpFnScenarioSideEffect) {\n return { formatVersion: 1 as const, name, sideEffect };\n}\n\nfunction createToolCallScenario(\n name: string,\n operation: Extract<McpFnRecordedOperation, { kind: \"tools.call\" }>,\n result: CallToolResult,\n): McpFnToolScenario {\n return {\n ...scenarioBase(name, \"non-idempotent\"),\n kind: \"tools.call\",\n tool: operation.name,\n ...(operation.arguments ? { arguments: operation.arguments } : {}),\n expect: {\n isError: Boolean(result.isError),\n ...(result.structuredContent !== undefined\n ? { structuredContent: result.structuredContent }\n : {}),\n },\n };\n}\n\nfunction createToolTaskScenario(\n name: string,\n operation: Extract<McpFnRecordedOperation, { kind: \"tools.call:task\" }>,\n): McpFnCreateTaskScenario {\n return {\n ...scenarioBase(name, \"non-idempotent\"),\n kind: operation.kind,\n tool: operation.name,\n ...(operation.arguments ? { arguments: operation.arguments } : {}),\n ...(operation.task ? { task: operation.task } : {}),\n };\n}\n\nfunction createResourceReadScenario(\n name: string,\n operation: Extract<McpFnRecordedOperation, { kind: \"resources.read\" }>,\n result: McpFnRecordedOperationResult,\n): McpFnResourceScenario {\n return {\n ...scenarioBase(name, \"none\"),\n kind: operation.kind,\n uri: operation.uri,\n expect: result,\n };\n}\n\nfunction createResourceLifecycleScenario(\n name: string,\n operation: Extract<McpFnRecordedOperation, { kind: \"resources.subscribe\" | \"resources.unsubscribe\" }>,\n): McpFnResourceScenario {\n return {\n ...scenarioBase(name, \"idempotent\"),\n kind: operation.kind,\n uri: operation.uri,\n };\n}\n\nfunction createTaskLifecycleScenario(\n name: string,\n operation: Extract<McpFnRecordedOperation, { kind: \"tasks.get\" | \"tasks.cancel\" }>,\n): McpFnTaskScenario {\n return {\n ...scenarioBase(name, operation.kind === \"tasks.cancel\" ? \"idempotent\" : \"none\"),\n kind: operation.kind,\n taskId: operation.taskId,\n };\n}\n\nfunction createTaskResultScenario(\n name: string,\n operation: Extract<McpFnRecordedOperation, { kind: \"tasks.result\" }>,\n result: McpFnRecordedOperationResult,\n): McpFnTaskScenario {\n return {\n ...scenarioBase(name, \"none\"),\n kind: operation.kind,\n taskId: operation.taskId,\n expect: result,\n };\n}\n\nfunction createTaskListScenario(\n name: string,\n operation: Extract<McpFnRecordedOperation, { kind: \"tasks.list\" }>,\n): McpFnTaskScenario {\n return {\n ...scenarioBase(name, \"none\"),\n kind: operation.kind,\n ...(operation.cursor ? { cursor: operation.cursor } : {}),\n };\n}\n\nfunction createPromptScenario(\n name: string,\n operation: Extract<McpFnRecordedOperation, { kind: \"prompts.get\" }>,\n result: McpFnRecordedOperationResult,\n): McpFnPromptScenario {\n return {\n ...scenarioBase(name, \"none\"),\n kind: operation.kind,\n prompt: operation.name,\n ...(operation.arguments ? { arguments: operation.arguments } : {}),\n expect: result,\n };\n}\n\n/** Validate an unknown scenario module before it reaches the shared runner. */\nexport function validateMcpFnScenarios(value: unknown): McpFnScenario[] {\n const artifact = isScenarioArtifact(value) ? value : undefined;\n if (artifact?.status === \"incomplete\") {\n throw new Error(`McpFn scenario artifact is incomplete: ${artifact.incompleteReason}`);\n }\n const scenarios = artifact?.scenarios ?? value;\n if (!Array.isArray(scenarios)) {\n throw new TypeError(\"Scenario module must export an array or mcpfn.scenarios artifact\");\n }\n for (const [index, scenario] of scenarios.entries()) {\n validateScenarioCandidate(scenario, index);\n }\n return scenarios as McpFnScenario[];\n}\n\nconst SCENARIO_KINDS_WITHOUT_REQUIRED_FIELDS = new Set([\n \"initialize\",\n \"tools.list\",\n \"resources.list\",\n \"resources.templates.list\",\n \"prompts.list\",\n \"tasks.list\",\n \"auth.assert\",\n]);\n\nfunction validateScenarioCandidate(scenario: unknown, index: number): void {\n if (!scenario || typeof scenario !== \"object\" || Array.isArray(scenario)) {\n throw new TypeError(`Invalid scenario at index ${index}`);\n }\n const candidate = scenario as Record<string, unknown>;\n validateScenarioIdentity(candidate, index);\n const kind = scenarioKind(candidate, index);\n validateScenarioOperation(candidate, kind, index);\n validateScenarioLimits(candidate, index);\n if (kind === \"events.expect\") validateEventScenario(candidate, index);\n validateScenarioMetadata(candidate, index);\n if (kind === \"auth.assert\") validateAuthScenario(candidate, index);\n}\n\nfunction validateScenarioIdentity(candidate: Record<string, unknown>, index: number): void {\n if (candidate.formatVersion !== undefined && candidate.formatVersion !== 1) {\n throw new TypeError(`Invalid scenario at index ${index}: unsupported formatVersion`);\n }\n if (typeof candidate.name !== \"string\" || !candidate.name.trim()) {\n throw new TypeError(`Invalid scenario at index ${index}: name is required`);\n }\n}\n\nfunction scenarioKind(candidate: Record<string, unknown>, index: number): string {\n const kind = candidate.kind ?? \"tools.call\";\n if (typeof kind !== \"string\") {\n throw new TypeError(`Invalid scenario at index ${index}: kind must be a string`);\n }\n return kind;\n}\n\nfunction validateScenarioOperation(\n candidate: Record<string, unknown>,\n kind: string,\n index: number,\n): void {\n const requiredField = requiredScenarioField(kind);\n if (requiredField && typeof candidate[requiredField] !== \"string\") {\n throw new TypeError(`Invalid scenario at index ${index}: ${kind} requires ${requiredField}`);\n }\n if (!requiredField && !SCENARIO_KINDS_WITHOUT_REQUIRED_FIELDS.has(kind)) {\n throw new TypeError(`Invalid scenario at index ${index}: unsupported kind ${kind}`);\n }\n}\n\nfunction validateScenarioLimits(candidate: Record<string, unknown>, index: number): void {\n if (\n candidate.timeoutMs !== undefined &&\n (!Number.isInteger(candidate.timeoutMs) || Number(candidate.timeoutMs) < 1 || Number(candidate.timeoutMs) > 300_000)\n ) {\n throw new TypeError(`Invalid scenario at index ${index}: timeoutMs must be 1..300000`);\n }\n if (\n candidate.variables !== undefined &&\n (\n !Array.isArray(candidate.variables) ||\n candidate.variables.some((entry) => typeof entry !== \"string\" || !/^[A-Z][A-Z0-9_]*$/.test(entry))\n )\n ) {\n throw new TypeError(`Invalid scenario at index ${index}: variables must be environment names`);\n }\n}\n\nfunction validateScenarioMetadata(candidate: Record<string, unknown>, index: number): void {\n if (\n candidate.status !== undefined &&\n candidate.status !== \"complete\" &&\n candidate.status !== \"incomplete\"\n ) {\n throw new TypeError(`Invalid scenario at index ${index}: status must be complete or incomplete`);\n }\n if (candidate.status === \"incomplete\" && typeof candidate.incompleteReason !== \"string\") {\n throw new TypeError(`Invalid scenario at index ${index}: incompleteReason is required`);\n }\n if (\n candidate.sideEffect !== undefined &&\n (typeof candidate.sideEffect !== \"string\" || ![\"none\", \"idempotent\", \"non-idempotent\"].includes(candidate.sideEffect))\n ) {\n throw new TypeError(`Invalid scenario at index ${index}: sideEffect is unsupported`);\n }\n}\n\nfunction validateEventScenario(candidate: Record<string, unknown>, index: number): void {\n if (\n candidate.minimum !== undefined &&\n (!Number.isSafeInteger(candidate.minimum) || Number(candidate.minimum) < 1)\n ) {\n throw new TypeError(\n `Invalid scenario at index ${index}: events.expect minimum must be a positive integer`,\n );\n }\n}\n\nfunction validateAuthScenario(candidate: Record<string, unknown>, index: number): void {\n const expectation = candidate.expect as Record<string, unknown> | undefined;\n if (\n typeof candidate.phase !== \"string\" ||\n !expectation ||\n typeof expectation.outcome !== \"string\" ||\n ![\"allowed\", \"denied\"].includes(expectation.outcome)\n ) {\n throw new TypeError(`Invalid scenario at index ${index}: auth.assert expectation is required`);\n }\n}\n\nexport function createMcpFnScenarioArtifact(\n scenarios: McpFnScenario[],\n options?: Omit<McpFnScenarioArtifact, \"formatVersion\" | \"kind\" | \"scenarios\">,\n): McpFnScenarioArtifact {\n const artifactOptions = options ?? { status: \"complete\" as const };\n return {\n formatVersion: 1,\n kind: \"mcpfn.scenarios\",\n ...artifactOptions,\n scenarios: validateMcpFnScenarios(scenarios),\n };\n}\n\nfunction isScenarioArtifact(value: unknown): value is McpFnScenarioArtifact {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return false;\n const candidate = value as Record<string, unknown>;\n if (candidate.kind !== \"mcpfn.scenarios\") return false;\n if (candidate.formatVersion !== 1) {\n throw new Error(\"Unsupported McpFn scenario artifact formatVersion\");\n }\n if (candidate.status !== \"complete\" && candidate.status !== \"incomplete\") {\n throw new Error(\"McpFn scenario artifact status must be complete or incomplete\");\n }\n if (candidate.status === \"incomplete\" && typeof candidate.incompleteReason !== \"string\") {\n throw new Error(\"Incomplete McpFn scenario artifact requires incompleteReason\");\n }\n return true;\n}\n\nexport async function runScenarios(\n client: McpFnTestClient<unknown>,\n scenarios: McpFnScenario[],\n options: McpFnScenarioRunOptions = {},\n): Promise<McpFnScenarioResult[]> {\n if (\n options.defaultTimeoutMs !== undefined &&\n (\n !Number.isInteger(options.defaultTimeoutMs) ||\n options.defaultTimeoutMs < 1 ||\n options.defaultTimeoutMs > 300_000\n )\n ) {\n throw new Error(\"defaultTimeoutMs must be an integer from 1 through 300000\");\n }\n if (\n options.maxScenarios !== undefined &&\n (!Number.isInteger(options.maxScenarios) || options.maxScenarios < 1)\n ) {\n throw new Error(\"maxScenarios must be a positive integer\");\n }\n if (\n options.maxErrorBytes !== undefined &&\n (!Number.isInteger(options.maxErrorBytes) || options.maxErrorBytes < 64)\n ) {\n throw new Error(\"maxErrorBytes must be an integer of at least 64\");\n }\n if (\n options.maxObservedEvents !== undefined &&\n (!Number.isInteger(options.maxObservedEvents) || options.maxObservedEvents < 1)\n ) {\n throw new Error(\"maxObservedEvents must be a positive integer\");\n }\n if (scenarios.length > (options.maxScenarios ?? 1_000)) {\n throw new Error(`Scenario count exceeds the configured cap of ${options.maxScenarios ?? 1_000}`);\n }\n const results: McpFnScenarioResult[] = [];\n const observedEvents: McpFnClientEvent[] = [];\n const maxObservedEvents = options.maxObservedEvents ?? 500;\n let droppedObservedEvents = 0;\n let attributedDroppedObservedEvents = 0;\n const pushResult = (result: McpFnScenarioResult): void => {\n const newlyDropped = droppedObservedEvents - attributedDroppedObservedEvents;\n results.push({\n ...result,\n ...(newlyDropped > 0\n ? { droppedObservedEvents: (result.droppedObservedEvents ?? 0) + newlyDropped }\n : {}),\n });\n attributedDroppedObservedEvents = droppedObservedEvents;\n };\n const unsubscribe = client.session.onEvent((event) => {\n observedEvents.push(event);\n if (observedEvents.length > maxObservedEvents) {\n observedEvents.shift();\n droppedObservedEvents += 1;\n }\n });\n let timedOutScenario: string | undefined;\n try {\n for (const scenario of scenarios) {\n const startedAt = performance.now();\n const operation = scenario.kind ?? \"tools.call\";\n const common = {\n formatVersion: 1 as const,\n name: scenario.name,\n operation,\n ...(isToolScenario(scenario) ? { tool: scenario.tool } : {}),\n sideEffect: scenario.sideEffect ?? defaultSideEffect(operation),\n };\n if (timedOutScenario) {\n pushResult({\n ...common,\n status: \"incomplete\",\n durationMs: 0,\n error: truncateError(`Skipped after timed-out scenario: ${timedOutScenario}`, options),\n });\n continue;\n }\n const resolved = resolveScenarioVariables(scenario, options.variables);\n if (resolved.missing.length > 0) {\n pushResult({\n ...common,\n status: \"incomplete\",\n durationMs: 0,\n error: truncateError(\n `Missing scenario variables: ${resolved.missing.join(\", \")}`,\n options,\n ),\n });\n continue;\n }\n if (scenario.status === \"incomplete\") {\n pushResult({\n ...common,\n status: \"incomplete\",\n durationMs: 0,\n error: truncateError(scenario.incompleteReason ?? \"Scenario is incomplete\", options),\n });\n continue;\n }\n const timeoutMs = scenario.timeoutMs ?? options.defaultTimeoutMs ?? 30_000;\n const controller = new AbortController();\n let timer: ReturnType<typeof setTimeout> | undefined;\n let timedOut = false;\n try {\n await Promise.race([\n executeScenario(client, resolved.scenario, {\n signal: controller.signal,\n timeout: timeoutMs,\n }, observedEvents, options),\n new Promise<never>((_resolve, reject) => {\n timer = setTimeout(() => {\n timedOut = true;\n controller.abort();\n reject(new McpFnAssertionError(`Scenario timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n }),\n ]);\n pushResult({\n ...common,\n status: \"passed\",\n durationMs: performance.now() - startedAt,\n });\n } catch (error) {\n pushResult({\n ...common,\n status: \"failed\",\n durationMs: performance.now() - startedAt,\n error: truncateError(error instanceof Error ? error.message : String(error), options),\n });\n if (timedOut) timedOutScenario = scenario.name;\n } finally {\n if (timer) clearTimeout(timer);\n }\n }\n } finally {\n const unattributed = droppedObservedEvents - attributedDroppedObservedEvents;\n const lastResult = results.at(-1);\n if (lastResult && unattributed > 0) {\n lastResult.droppedObservedEvents =\n (lastResult.droppedObservedEvents ?? 0) + unattributed;\n }\n unsubscribe();\n }\n return results;\n}\n\nexport interface McpFnScenarioRunOptions {\n defaultTimeoutMs?: number;\n maxScenarios?: number;\n maxErrorBytes?: number;\n /** Observed client-event count cap. Defaults to 500. */\n maxObservedEvents?: number;\n variables?: Record<string, string | undefined>;\n auth?(scenario: McpFnAuthScenario, signal: AbortSignal): Promise<{\n outcome: \"allowed\" | \"denied\";\n code?: string;\n }>;\n}\n\nfunction resolveScenarioVariables(\n scenario: McpFnScenario,\n supplied: Record<string, string | undefined> | undefined,\n): { scenario: McpFnScenario; missing: string[] } {\n const values = { ...process.env, ...supplied };\n const required = new Set(scenario.variables ?? []);\n const marker = /\\$\\{([A-Z][A-Z0-9_]*)\\}/g;\n const encodedMarker = /%24%7[Bb]([A-Z][A-Z0-9_]*)%7[Dd]/g;\n const visit = (value: unknown): unknown => {\n if (typeof value === \"string\") {\n for (const match of value.matchAll(marker)) required.add(match[1]);\n for (const match of value.matchAll(encodedMarker)) required.add(match[1]);\n return value\n .replace(marker, (original, name: string) => values[name] ?? original)\n .replace(encodedMarker, (original, name: string) =>\n values[name] === undefined ? original : encodeURIComponent(values[name]),\n );\n }\n if (Array.isArray(value)) return value.map(visit);\n if (value && typeof value === \"object\") {\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>).map(([key, entry]) => [key, visit(entry)]),\n );\n }\n return value;\n };\n const resolved = visit(scenario) as McpFnScenario;\n return {\n scenario: resolved,\n missing: [...required]\n .filter((name) => values[name] === undefined)\n .sort(compareCodeUnits),\n };\n}\n\nexport function createMcpFnScenarioReport(\n results: McpFnScenarioResult[],\n options: { manifestHash?: string; maxBytes?: number } = {},\n): McpFnScenarioReport {\n const failed = results.filter((result) => result.status === \"failed\").length;\n const incomplete = results.filter((result) => result.status === \"incomplete\").length;\n const droppedObservedEvents = results.reduce(\n (total, result) => total + (result.droppedObservedEvents ?? 0),\n 0,\n );\n const report: McpFnScenarioReport = {\n formatVersion: 1,\n kind: \"mcpfn.scenario-report\",\n status: incomplete === 0 && droppedObservedEvents === 0 ? \"complete\" : \"incomplete\",\n ...(options.manifestHash ? { manifestHash: options.manifestHash } : {}),\n total: results.length,\n passed: results.length - failed - incomplete,\n failed,\n incomplete,\n droppedResults: 0,\n droppedObservedEvents,\n ...(droppedObservedEvents > 0\n ? { incompleteReason: \"Observed client events exceeded maxObservedEvents\" }\n : {}),\n results: structuredClone(results),\n };\n const maxBytes = options.maxBytes ?? 1_048_576;\n if (!Number.isInteger(maxBytes) || maxBytes < 1_024) {\n throw new Error(\"maxBytes must be an integer of at least 1024\");\n }\n if (serializedBytes(report) > maxBytes) {\n report.status = \"incomplete\";\n report.incompleteReason = \"Report content exceeded maxBytes and was truncated\";\n }\n while (serializedBytes(report) > maxBytes && report.results.length > 0) {\n report.results.pop();\n report.droppedResults += 1;\n }\n if (report.droppedResults > 0) {\n report.status = \"incomplete\";\n }\n if (serializedBytes(report) > maxBytes) {\n throw new Error(\"The minimum scenario report exceeds maxBytes\");\n }\n return report;\n}\n\nfunction serializedBytes(value: unknown): number {\n return new TextEncoder().encode(JSON.stringify(value)).byteLength;\n}\n\nasync function executeScenario(\n client: McpFnTestClient<unknown>,\n scenario: McpFnScenario,\n requestOptions: { signal: AbortSignal; timeout: number },\n observedEvents: McpFnClientEvent[],\n runOptions: McpFnScenarioRunOptions,\n): Promise<void> {\n const kind = scenario.kind ?? \"tools.call\";\n if (isInventoryScenario(scenario)) {\n await executeInventoryScenario(client, scenario, requestOptions);\n return;\n }\n switch (scenario.kind) {\n case undefined:\n case \"tools.call\":\n return executeToolScenario(client, scenario, requestOptions);\n case \"initialize\":\n return executeInitializeScenario(client, scenario);\n case \"resources.read\":\n return assertExpectedAsync(client.readResource(scenario.uri, requestOptions), scenario.expect);\n case \"resources.subscribe\":\n return client.subscribeResource(scenario.uri, requestOptions);\n case \"resources.unsubscribe\":\n return client.unsubscribeResource(scenario.uri, requestOptions);\n case \"prompts.get\":\n return assertExpectedAsync(\n client.getPrompt(scenario.prompt, scenario.arguments, requestOptions),\n scenario.expect,\n );\n case \"tools.call:task\":\n return assertExpectedAsync(\n client.createToolTask(scenario.tool, scenario.arguments, scenario.task, requestOptions),\n scenario.expect,\n );\n case \"tasks.get\":\n return assertExpectedAsync(client.getTask(scenario.taskId!, requestOptions), scenario.expect);\n case \"tasks.result\":\n return assertExpectedAsync(client.getTaskResult(scenario.taskId!, requestOptions), scenario.expect);\n case \"tasks.cancel\":\n return assertExpectedAsync(client.cancelTask(scenario.taskId!, requestOptions), scenario.expect);\n case \"tasks.list\":\n return assertExpectedAsync(client.listTasks(scenario.cursor, requestOptions), scenario.expect);\n case \"events.expect\":\n return executeEventScenario(scenario, observedEvents);\n case \"auth.assert\":\n return executeAuthScenario(scenario, requestOptions.signal, runOptions);\n }\n throw new McpFnAssertionError(`Unsupported scenario operation ${kind}`);\n}\n\nasync function executeToolScenario(\n client: McpFnTestClient<unknown>,\n scenario: McpFnToolScenario,\n requestOptions: { signal: AbortSignal; timeout: number },\n): Promise<void> {\n const result = await client.callTool(\n scenario.tool,\n scenario.arguments,\n requestOptions,\n );\n assertToolResult(result, scenario);\n await scenario.verify?.(result);\n}\n\nfunction assertToolResult(result: CallToolResult, scenario: McpFnToolScenario): void {\n if (result.isError && scenario.expect?.isError === undefined) {\n throw new McpFnAssertionError(\n \"Tool returned isError=true without an explicit expect.isError=true assertion\",\n );\n }\n if (\n scenario.expect?.isError !== undefined &&\n Boolean(result.isError) !== scenario.expect.isError\n ) {\n throw new McpFnAssertionError(\n `Expected isError=${scenario.expect.isError}, received ${Boolean(result.isError)}`,\n );\n }\n if (\n scenario.expect &&\n Object.hasOwn(scenario.expect, \"structuredContent\") &&\n stableJson(result.structuredContent) !== stableJson(scenario.expect.structuredContent)\n ) {\n throw new McpFnAssertionError(\n `Structured result mismatch\\nexpected: ${stableJson(scenario.expect.structuredContent)}\\nactual: ${stableJson(result.structuredContent)}`,\n );\n }\n if (scenario.expect?.structuredTextParity) assertStructuredTextParity(result);\n}\n\nfunction executeInitializeScenario(\n client: McpFnTestClient<unknown>,\n scenario: McpFnInitializeScenario,\n): void {\n const actual = client.client.getServerCapabilities() ?? {};\n if (scenario.expectCapabilities && stableJson(actual) !== stableJson(scenario.expectCapabilities)) {\n throw new McpFnAssertionError(\n `Capability mismatch\\nexpected: ${stableJson(scenario.expectCapabilities)}\\nactual: ${stableJson(actual)}`,\n );\n }\n}\n\nasync function executeInventoryScenario(\n client: McpFnTestClient<unknown>,\n scenario: McpFnInventoryScenario,\n requestOptions: { signal: AbortSignal; timeout: number },\n): Promise<void> {\n const values = await listScenarioInventory(client, scenario.kind, requestOptions);\n if (!scenario.expectNames) return;\n const actual = values.map((value) => value.name).sort(compareCodeUnits);\n const expected = [...scenario.expectNames].sort(compareCodeUnits);\n if (stableJson(actual) !== stableJson(expected)) {\n throw new McpFnAssertionError(\n `Inventory mismatch\\nexpected: ${stableJson(expected)}\\nactual: ${stableJson(actual)}`,\n );\n }\n}\n\nasync function assertExpectedAsync(actual: Promise<unknown>, expected: unknown): Promise<void> {\n assertExpected(await actual, expected);\n}\n\nfunction executeEventScenario(\n scenario: McpFnEventScenario,\n observedEvents: McpFnClientEvent[],\n): void {\n const matching = observedEvents.filter((event) => event.kind === scenario.event);\n if (matching.length < (scenario.minimum ?? 1)) {\n throw new McpFnAssertionError(\n `Expected at least ${scenario.minimum ?? 1} ${scenario.event} event(s), received ${matching.length}`,\n );\n }\n if (scenario.expectPayload !== undefined) {\n assertExpected(matching.at(-1)?.payload, scenario.expectPayload);\n }\n}\n\nasync function executeAuthScenario(\n scenario: McpFnAuthScenario,\n signal: AbortSignal,\n runOptions: McpFnScenarioRunOptions,\n): Promise<void> {\n if (!runOptions.auth) {\n throw new McpFnAssertionError(\"auth.assert requires a scenario auth adapter\");\n }\n assertExpected(await runOptions.auth(scenario, signal), scenario.expect);\n}\n\nfunction truncateError(value: string, options: McpFnScenarioRunOptions): string {\n const redacted = String(redactOAuthValue(value));\n const maxBytes = options.maxErrorBytes ?? 4_096;\n const bytes = new TextEncoder().encode(redacted);\n if (bytes.byteLength <= maxBytes) return redacted;\n return `${new TextDecoder().decode(bytes.slice(0, Math.max(0, maxBytes - 16)))}...[TRUNCATED]`;\n}\n\nfunction defaultSideEffect(operation: string): McpFnScenarioSideEffect {\n if (operation === \"tools.call\" || operation === \"tools.call:task\") {\n return \"non-idempotent\";\n }\n if (operation === \"tasks.cancel\") return \"idempotent\";\n return \"none\";\n}\n\nfunction compareCodeUnits(left: string, right: string): number {\n if (left < right) return -1;\n if (left > right) return 1;\n return 0;\n}\n\nfunction assertExpected(actual: unknown, expected: unknown): void {\n if (expected !== undefined && stableJson(actual) !== stableJson(expected)) {\n throw new McpFnAssertionError(\n `Scenario result mismatch\\nexpected: ${stableJson(expected)}\\nactual: ${stableJson(actual)}`,\n );\n }\n}\n\nfunction isToolScenario(scenario: McpFnScenario): scenario is McpFnToolScenario {\n return \"tool\" in scenario;\n}\n\nfunction isInventoryScenario(scenario: McpFnScenario): scenario is McpFnInventoryScenario {\n return [\"tools.list\", \"resources.list\", \"resources.templates.list\", \"prompts.list\"]\n .includes(scenario.kind ?? \"\");\n}\n\nfunction requiredScenarioField(kind: string): string | undefined {\n switch (kind) {\n case \"tools.call\":\n case \"tools.call:task\":\n return \"tool\";\n case \"resources.read\":\n case \"resources.subscribe\":\n case \"resources.unsubscribe\":\n return \"uri\";\n case \"prompts.get\":\n return \"prompt\";\n case \"tasks.get\":\n case \"tasks.result\":\n case \"tasks.cancel\":\n return \"taskId\";\n case \"events.expect\":\n return \"event\";\n default:\n return undefined;\n }\n}\n\nasync function listScenarioInventory(\n client: McpFnTestClient<unknown>,\n kind: McpFnInventoryScenario[\"kind\"],\n requestOptions: { signal: AbortSignal; timeout: number },\n) {\n switch (kind) {\n case \"tools.list\":\n return client.listTools(requestOptions);\n case \"resources.list\":\n return client.listResources(requestOptions);\n case \"resources.templates.list\":\n return client.listResourceTemplates(requestOptions);\n case \"prompts.list\":\n return client.listPrompts(requestOptions);\n }\n}\n","import type { Implementation, ServerCapabilities } from \"@modelcontextprotocol/sdk/types.js\";\nimport type {\n McpFnDiagnosticEvent,\n McpFnTarget,\n McpFnTargetDescriptor,\n} from \"@mcpfn/client\";\nimport type { McpFnManifest } from \"@mcpfn/core\";\nimport { redactOAuthValue } from \"@superfunctions/oauth-core\";\n\nimport { assertManifestContract } from \"./assertions.js\";\nimport { McpFnTestClient, type McpFnTestClientOptions } from \"./client.js\";\nimport {\n runScenarios,\n type McpFnScenario,\n type McpFnScenarioResult,\n} from \"./scenarios.js\";\n\nexport interface RunMcpFnTargetSuiteOptions {\n target: McpFnTarget;\n scenarios?: McpFnScenario[];\n manifest?: McpFnManifest;\n expectedToolNames?: readonly string[];\n clientInfo?: Implementation;\n client?: McpFnTestClientOptions;\n scenarioRun?: NonNullable<Parameters<typeof runScenarios>[2]>;\n /** Aggregate JSON size cap. Defaults to 1 MiB. */\n maxReportBytes?: number;\n /** Diagnostic timeline count cap. Defaults to 500. */\n maxTimelineEvents?: number;\n}\n\nexport interface McpFnTargetSuiteReport {\n formatVersion: 1;\n kind: \"mcpfn.target-suite-report\";\n status: \"complete\" | \"incomplete\";\n runtime: { node: string; scenarioFormatVersion: 1 };\n ok: boolean;\n target: McpFnTargetDescriptor;\n server?: Implementation;\n capabilities?: ServerCapabilities;\n manifestChecked: boolean;\n manifestHash?: string;\n total: number;\n passed: number;\n failed: number;\n incomplete: number;\n droppedResults: number;\n droppedObservedEvents: number;\n incompleteReason?: string;\n timeline: McpFnDiagnosticEvent[];\n droppedTimelineEvents: number;\n results: McpFnScenarioResult[];\n}\n\n/** Runs local, stdio, HTTP, or custom targets through the production session engine. */\nexport async function runMcpFnTargetSuite(\n options: RunMcpFnTargetSuiteOptions,\n): Promise<McpFnTargetSuiteReport> {\n const timeline: McpFnDiagnosticEvent[] = [];\n let droppedTimelineEvents = 0;\n const maxTimelineEvents = options.maxTimelineEvents ?? 500;\n if (!Number.isInteger(maxTimelineEvents) || maxTimelineEvents < 1) {\n throw new Error(\"maxTimelineEvents must be a positive integer\");\n }\n const maxReportBytes = options.maxReportBytes ?? 1_048_576;\n validateReportCap(maxReportBytes);\n const consumerDiagnostic = options.client?.diagnostics;\n const client = await McpFnTestClient.connectTarget(\n options.target,\n options.clientInfo ?? { name: \"mcpfn-suite\", version: \"0.0.1\" },\n {\n ...options.client,\n diagnostics: async (event) => {\n timeline.push(redactOAuthValue(event) as unknown as McpFnDiagnosticEvent);\n if (timeline.length > maxTimelineEvents) {\n timeline.shift();\n droppedTimelineEvents += 1;\n }\n await consumerDiagnostic?.(event);\n },\n },\n );\n const execution = await (async () => {\n try {\n if (options.manifest) {\n await assertManifestContract(client, options.manifest, {\n expectedToolNames: options.expectedToolNames,\n });\n }\n const results = await runScenarios(client, options.scenarios ?? [], options.scenarioRun);\n return {\n results,\n server: client.session.getServerVersion(),\n capabilities: client.session.getServerCapabilities(),\n };\n } finally {\n await client.close();\n }\n })();\n const results = execution.results;\n const failed = results.filter((result) => result.status === \"failed\").length;\n const incomplete = results.filter((result) => result.status === \"incomplete\").length;\n const droppedObservedEvents = results.reduce(\n (total, result) => total + (result.droppedObservedEvents ?? 0),\n 0,\n );\n const artifactIncomplete = incomplete > 0 ||\n droppedTimelineEvents > 0 ||\n droppedObservedEvents > 0;\n const report: McpFnTargetSuiteReport = {\n formatVersion: 1,\n kind: \"mcpfn.target-suite-report\",\n status: artifactIncomplete ? \"incomplete\" : \"complete\",\n runtime: { node: process.version, scenarioFormatVersion: 1 },\n ok: failed === 0 && !artifactIncomplete,\n target: redactOAuthValue(\n options.target.describe(),\n ) as unknown as McpFnTargetDescriptor,\n server: execution.server,\n capabilities: execution.capabilities,\n manifestChecked: Boolean(options.manifest),\n ...(options.manifest ? { manifestHash: options.manifest.hash } : {}),\n total: results.length,\n passed: results.length - failed - incomplete,\n failed,\n incomplete,\n droppedResults: 0,\n droppedObservedEvents,\n ...(droppedTimelineEvents > 0 || droppedObservedEvents > 0\n ? {\n incompleteReason: [\n ...(droppedTimelineEvents > 0\n ? [\"Diagnostic timeline exceeded maxTimelineEvents\"]\n : []),\n ...(droppedObservedEvents > 0\n ? [\"Observed client events exceeded maxObservedEvents\"]\n : []),\n ].join(\"; \"),\n }\n : {}),\n timeline,\n droppedTimelineEvents,\n results,\n };\n return enforceReportCap(report, maxReportBytes);\n}\n\nfunction enforceReportCap(\n report: McpFnTargetSuiteReport,\n maxBytes: number,\n): McpFnTargetSuiteReport {\n validateReportCap(maxBytes);\n const bounded = structuredClone(report);\n if (jsonBytes(bounded) > maxBytes) {\n bounded.ok = false;\n bounded.status = \"incomplete\";\n bounded.incompleteReason = \"Report content exceeded maxReportBytes and was truncated\";\n }\n while (jsonBytes(bounded) > maxBytes && bounded.results.length > 0) {\n bounded.results.pop();\n bounded.droppedResults += 1;\n }\n if (jsonBytes(bounded) > maxBytes) {\n bounded.target = { kind: report.target.kind };\n bounded.server = undefined;\n bounded.capabilities = undefined;\n bounded.timeline = [];\n bounded.droppedTimelineEvents += report.timeline.length;\n }\n if (bounded.droppedResults > 0 || jsonBytes(bounded) > maxBytes) {\n bounded.ok = false;\n bounded.status = \"incomplete\";\n bounded.incompleteReason = \"Report content exceeded maxReportBytes and was truncated\";\n }\n if (jsonBytes(bounded) > maxBytes) {\n throw new Error(\"The minimum target suite report exceeds maxReportBytes\");\n }\n return bounded;\n}\n\nfunction validateReportCap(maxBytes: number): void {\n if (!Number.isInteger(maxBytes) || maxBytes < 1_024) {\n throw new Error(\"maxReportBytes must be an integer of at least 1024\");\n }\n}\n\nfunction jsonBytes(value: unknown): number {\n return new TextEncoder().encode(JSON.stringify(value)).byteLength;\n}\n"],"mappings":"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","names":["path","createServer","redactOAuthValue","redactOAuthValue","results"]}
|