[CmdletBinding()] param( [Parameter(Mandatory)] [uri]$Url, [string[]]$Scenario = @("server-stateless", "tools-list", "json-schema-2020-12", "server-sse-multiple-streams", "dns-rebinding-protection", "caching", "http-header-validation"), [string]$EvidenceDirectory = "artifacts/evidence/mcp-2026-07-28/conformance-production" ) $ErrorActionPreference = "Stop" if (-not $Url.IsLoopback) { throw "Conformance target must be loopback." } $repository = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path $runnerDirectory = Join-Path $repository "build/conformance-runner" $packageJson = Join-Path $runnerDirectory "node_modules/@modelcontextprotocol/conformance/package.json" if (-not (Test-Path -LiteralPath $packageJson)) { throw "Offline runner is absent. Run scripts/Acquire-McpConformance.ps1 first." } $metadata = Get-Content -Raw -LiteralPath $packageJson | ConvertFrom-Json if ($metadata.version -ne "0.2.0-alpha.11") { throw "Unexpected conformance version: $($metadata.version)" } $cli = Join-Path (Split-Path $packageJson) $metadata.bin.conformance $evidence = [IO.Path]::GetFullPath($EvidenceDirectory, $repository) New-Item -ItemType Directory -Force -Path $evidence | Out-Null $applicationFailures = @() $runnerLimitations = @() foreach ($name in $Scenario) { $output = Join-Path $evidence $name & node $cli server --url $Url.AbsoluteUri --scenario $name --spec-version 2026-07-28 --output-dir $output --verbose 2>&1 | Tee-Object -FilePath (Join-Path $evidence "$name.txt") $runnerExitCode = $LASTEXITCODE $resultDirectory = Get-ChildItem -LiteralPath $output -Directory | Sort-Object LastWriteTimeUtc -Descending | Select-Object -First 1 if ($null -eq $resultDirectory) { $runnerLimitations += "$name`:runner_exit_$runnerExitCode`:no_result_directory" continue } $checksPath = Join-Path $resultDirectory.FullName "checks.json" if (-not (Test-Path -LiteralPath $checksPath)) { $runnerLimitations += "$name`:runner_exit_$runnerExitCode`:checks_missing" continue } $failedChecks = @((Get-Content -Raw -LiteralPath $checksPath | ConvertFrom-Json) | Where-Object status -eq "FAILURE") foreach ($check in $failedChecks) { $message = [string]$check.errorMessage if ($message -match "Not testable:" -or $message -match "Tool 'json_schema_2020_12_tool' not found" -or $message -match "Method '(prompts/list|resources/list|resources/templates/list)' is not available") { $runnerLimitations += "$name`:$($check.id) - $message" } else { $applicationFailures += "$name`:$($check.id) - $message" } } if ($runnerExitCode -ne 0 -and $failedChecks.Count -eq 0) { $runnerLimitations += "$name`:runner_exit_$runnerExitCode`:all_checks_passed" } } [ordered]@{ runner_version = $metadata.version scenarios = $Scenario application_failure_count = $applicationFailures.Count application_failures = $applicationFailures runner_limitation_count = $runnerLimitations.Count runner_limitations = $runnerLimitations } | ConvertTo-Json -Depth 5 | Set-Content -Encoding utf8 -LiteralPath (Join-Path $evidence "summary.json") if ($applicationFailures.Count -ne 0) { throw "$($applicationFailures.Count) application conformance check(s) failed." }