@certscore/mcp 0.2.16 → 0.2.18

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.
@@ -14405,8 +14405,8 @@ var CertScoreClient = class {
14405
14405
  }
14406
14406
  const elapsedMs = Date.now() - options.startedAt;
14407
14407
  const fallbackMs = options.adaptivePolling ? adaptivePollIntervalMs(elapsedMs) : options.pollIntervalMs;
14408
- const delay = Math.min(retryDelayMs(status, retryAfterSeconds, fallbackMs), Math.max(0, options.maxWaitMs - elapsedMs));
14409
- await sleep(delay, options.signal);
14408
+ const delay2 = Math.min(retryDelayMs(status, retryAfterSeconds, fallbackMs), Math.max(0, options.maxWaitMs - elapsedMs));
14409
+ await sleep(delay2, options.signal);
14410
14410
  const pollUrl = this.statusUrlFor(status);
14411
14411
  const response = await this.fetch(pollUrl, { signal: options.signal });
14412
14412
  if (response.status === 202 || response.status === 200 || response.status === 429) {
@@ -14442,8 +14442,8 @@ var CertScoreClient = class {
14442
14442
  }
14443
14443
  const elapsedMs = Date.now() - options.startedAt;
14444
14444
  const fallbackMs = options.adaptivePolling ? adaptivePollIntervalMs(elapsedMs) : options.pollIntervalMs;
14445
- const delay = Math.min(retryDelayMs(status, void 0, fallbackMs), Math.max(0, options.maxWaitMs - elapsedMs));
14446
- await sleep(delay, options.signal);
14445
+ const delay2 = Math.min(retryDelayMs(status, void 0, fallbackMs), Math.max(0, options.maxWaitMs - elapsedMs));
14446
+ await sleep(delay2, options.signal);
14447
14447
  let response = await this.fetch(this.scanResourceStatusUrlFor(status), { signal: options.signal, internalMcpOperation: options.internalMcpOperation });
14448
14448
  if (response.status === 404 && status.jobId) {
14449
14449
  response = await this.fetch(this.statusUrlFor(status), { signal: options.signal, internalMcpOperation: options.internalMcpOperation });
@@ -18675,6 +18675,131 @@ var coerce = {
18675
18675
  };
18676
18676
  var NEVER = INVALID;
18677
18677
 
18678
+ // ../certscore-api-contracts/src/scan-observation-results.ts
18679
+ var apiV2PostRefusalObservationSchema = external_exports.object({
18680
+ status: external_exports.enum(["confirmed_observation", "confirmed_clean", "unconfirmed", "not_attempted", "unsupported", "aborted"]),
18681
+ refusalExercised: external_exports.boolean(),
18682
+ observationCount: external_exports.number().int().min(0),
18683
+ productionProjectable: external_exports.boolean(),
18684
+ evidenceDisposition: external_exports.enum(["confirmed", "indeterminate"]),
18685
+ indeterminateReason: external_exports.string().min(1).max(160).nullable(),
18686
+ verdict: external_exports.enum([
18687
+ "eligible_nonessential_activity_observed_after_confirmed_refusal",
18688
+ "retained_consent_signal_contradiction_observed_after_confirmed_refusal",
18689
+ "no_eligible_nonessential_activity_observed_during_completed_window",
18690
+ "no_confirmed_post_refusal_verdict"
18691
+ ]),
18692
+ interpretation: external_exports.string().min(1).max(500),
18693
+ observationStrategy: external_exports.enum(["stop_on_first_eligible_activity", "not_applicable"]),
18694
+ termination: external_exports.object({
18695
+ kind: external_exports.enum(["evidence_satisfied", "window_elapsed", "unavailable"]),
18696
+ intentional: external_exports.boolean(),
18697
+ trigger: external_exports.enum([
18698
+ "non_essential_request_observed",
18699
+ "non_essential_storage_write_observed",
18700
+ "refusal_signal_contradiction_observed",
18701
+ "window_elapsed",
18702
+ "reject_path_timeout",
18703
+ "worker_failed",
18704
+ "unavailable"
18705
+ ])
18706
+ }).strict(),
18707
+ completedAt: external_exports.string().nullable(),
18708
+ coverageLimitations: external_exports.array(external_exports.string()).max(24),
18709
+ /** @deprecated Use coverageLimitations. Retained for API compatibility. */
18710
+ limitations: external_exports.array(external_exports.string()).max(24)
18711
+ }).strict();
18712
+ var apiV2PostAcceptObservationSchema = external_exports.object({
18713
+ status: external_exports.enum(["confirmed_observation", "confirmed_clean", "unconfirmed", "not_attempted", "unsupported", "aborted"]),
18714
+ acceptanceExercised: external_exports.boolean(),
18715
+ observationCount: external_exports.number().int().min(0),
18716
+ productionProjectable: external_exports.boolean(),
18717
+ evidenceDisposition: external_exports.enum(["confirmed", "indeterminate"]),
18718
+ indeterminateReason: external_exports.string().min(1).max(160).nullable(),
18719
+ verdict: external_exports.enum([
18720
+ "eligible_nonessential_activity_observed_after_confirmed_acceptance",
18721
+ "retained_consent_signal_contradiction_observed_after_confirmed_acceptance",
18722
+ "no_eligible_nonessential_activity_observed_during_completed_window",
18723
+ "no_confirmed_post_accept_verdict"
18724
+ ]),
18725
+ interpretation: external_exports.string().min(1).max(500),
18726
+ observationStrategy: external_exports.enum(["stop_on_first_eligible_activity", "not_applicable"]),
18727
+ termination: external_exports.object({
18728
+ kind: external_exports.enum(["evidence_satisfied", "window_elapsed", "unavailable"]),
18729
+ intentional: external_exports.boolean(),
18730
+ trigger: external_exports.enum([
18731
+ "non_essential_request_observed",
18732
+ "non_essential_storage_write_observed",
18733
+ "acceptance_signal_contradiction_observed",
18734
+ "window_elapsed",
18735
+ "accept_control_not_observed",
18736
+ "accept_path_timeout",
18737
+ "accept_observation_window_truncated",
18738
+ "worker_failed",
18739
+ "unavailable"
18740
+ ])
18741
+ }).strict(),
18742
+ completedAt: external_exports.string().nullable(),
18743
+ coverageLimitations: external_exports.array(external_exports.string()).max(24),
18744
+ /** @deprecated Use coverageLimitations. Retained for API compatibility. */
18745
+ limitations: external_exports.array(external_exports.string()).max(24)
18746
+ }).strict();
18747
+ var apiV2GpcComparisonDeltaSchema = external_exports.object({
18748
+ baselineCount: external_exports.number().int().nonnegative(),
18749
+ gpcCount: external_exports.number().int().nonnegative(),
18750
+ countDelta: external_exports.number().int(),
18751
+ baselineOnly: external_exports.array(external_exports.string().min(1).max(500)).max(100),
18752
+ gpcOnly: external_exports.array(external_exports.string().min(1).max(500)).max(100),
18753
+ shared: external_exports.array(external_exports.string().min(1).max(500)).max(100)
18754
+ }).strict();
18755
+ var apiV2GpcResponseSchema = external_exports.object({
18756
+ status: external_exports.enum(["responsive", "no_observable_response", "indeterminate"]),
18757
+ findingTitle: external_exports.enum(["GPC response", "No observable GPC response"]),
18758
+ summary: external_exports.string().min(1).max(2e3),
18759
+ scoreEffect: external_exports.literal("none"),
18760
+ legalInterpretation: external_exports.literal("not_assessed"),
18761
+ comparison: external_exports.object({
18762
+ comparable: external_exports.boolean(),
18763
+ protocol: external_exports.literal("passive_baseline_with_sec_gpc"),
18764
+ baselineArtifact: external_exports.object({
18765
+ lane: external_exports.literal("runtime_evidence"),
18766
+ sha256: external_exports.string().regex(/^[a-f0-9]{64}$/),
18767
+ sizeBytes: external_exports.number().int().nonnegative()
18768
+ }).strict(),
18769
+ gpcArtifact: external_exports.object({
18770
+ lane: external_exports.literal("gpc_observation"),
18771
+ sha256: external_exports.string().regex(/^[a-f0-9]{64}$/),
18772
+ sizeBytes: external_exports.number().int().nonnegative()
18773
+ }).strict(),
18774
+ enabledProof: external_exports.object({
18775
+ secGpcHeaderValue: external_exports.literal("1"),
18776
+ requestsWithSecGpc: external_exports.number().int().nonnegative(),
18777
+ requestEventIds: external_exports.array(external_exports.string().min(1).max(160)).max(100),
18778
+ navigatorGlobalPrivacyControl: external_exports.literal(true)
18779
+ }).strict(),
18780
+ deltas: external_exports.object({
18781
+ cookies: apiV2GpcComparisonDeltaSchema,
18782
+ trackers: apiV2GpcComparisonDeltaSchema,
18783
+ advertisingOrMeasurementActivity: apiV2GpcComparisonDeltaSchema,
18784
+ consentOrCmpBehavior: apiV2GpcComparisonDeltaSchema
18785
+ }).strict(),
18786
+ limitationKeys: external_exports.array(external_exports.string().min(1).max(160)).max(24)
18787
+ }).strict(),
18788
+ californiaPolicy: external_exports.object({
18789
+ applied: external_exports.boolean(),
18790
+ deductionPoints: external_exports.union([external_exports.literal(0), external_exports.literal(15)])
18791
+ }).strict(),
18792
+ evidenceUrl: external_exports.string().url()
18793
+ }).strict().superRefine((response, context) => {
18794
+ if (response.californiaPolicy.applied !== (response.californiaPolicy.deductionPoints === 15)) {
18795
+ context.addIssue({
18796
+ code: external_exports.ZodIssueCode.custom,
18797
+ message: "California GPC policy application must match its deduction.",
18798
+ path: ["californiaPolicy"]
18799
+ });
18800
+ }
18801
+ });
18802
+
18678
18803
  // ../certscore-api-contracts/src/scan-no-go.ts
18679
18804
  var publicScanNoGoReasonCodes = [
18680
18805
  "blank_or_unusable_page",
@@ -18878,6 +19003,9 @@ var pulseResponseSchema = external_exports.object({
18878
19003
  scanStatus: external_exports.string().optional(),
18879
19004
  resultDisposition: scanResultDispositionSchema.optional(),
18880
19005
  noGo: scanNoGoResultSchema.optional(),
19006
+ gpcResponse: apiV2GpcResponseSchema.nullable().optional(),
19007
+ postAcceptObservation: apiV2PostAcceptObservationSchema.nullable().optional(),
19008
+ postRefusalObservation: apiV2PostRefusalObservationSchema.nullable().optional(),
18881
19009
  summary: pulseSummarySchema.optional(),
18882
19010
  topFindings: external_exports.array(pulseFindingSchema).optional(),
18883
19011
  transportSecurity: pulseTransportSecuritySchema.optional(),
@@ -18929,6 +19057,7 @@ var pulseErrorSchema = external_exports.object({
18929
19057
  type: external_exports.literal("certscore_pulse_error"),
18930
19058
  error: external_exports.object({
18931
19059
  code: pulseErrorCodeSchema,
19060
+ reasonCode: external_exports.enum(["non_public_target"]).nullable().optional(),
18932
19061
  message: external_exports.string(),
18933
19062
  retryAfterSeconds: external_exports.number().int().nullable().optional(),
18934
19063
  recommendedNextAction: external_exports.string().nullable().optional(),
@@ -18968,47 +19097,6 @@ function isCanonicalScanId(value) {
18968
19097
  }
18969
19098
  var apiV2Disclaimer = "CertScore outputs are automated public-web observations for human and agentic review. They are not legal advice, certification, or a compliance determination.";
18970
19099
  var apiV2ScanStatusSchema = external_exports.enum(["queued", "running", "finalizing", "completed", "completed_limited", "failed", "expired", "rate_limited"]);
18971
- var apiV2PostRefusalObservationSchema = external_exports.object({
18972
- status: external_exports.enum([
18973
- "confirmed_observation",
18974
- "confirmed_clean",
18975
- "unconfirmed",
18976
- "not_attempted",
18977
- "unsupported",
18978
- "aborted"
18979
- ]),
18980
- refusalExercised: external_exports.boolean(),
18981
- observationCount: external_exports.number().int().min(0),
18982
- productionProjectable: external_exports.boolean(),
18983
- verdict: external_exports.enum([
18984
- "eligible_nonessential_activity_observed_after_confirmed_refusal",
18985
- "retained_consent_signal_contradiction_observed_after_confirmed_refusal",
18986
- "no_eligible_nonessential_activity_observed_during_completed_window",
18987
- "no_confirmed_post_refusal_verdict"
18988
- ]),
18989
- interpretation: external_exports.string().min(1).max(500),
18990
- observationStrategy: external_exports.enum([
18991
- "stop_on_first_eligible_activity",
18992
- "not_applicable"
18993
- ]),
18994
- termination: external_exports.object({
18995
- kind: external_exports.enum(["evidence_satisfied", "window_elapsed", "unavailable"]),
18996
- intentional: external_exports.boolean(),
18997
- trigger: external_exports.enum([
18998
- "non_essential_request_observed",
18999
- "non_essential_storage_write_observed",
19000
- "refusal_signal_contradiction_observed",
19001
- "window_elapsed",
19002
- "reject_path_timeout",
19003
- "worker_failed",
19004
- "unavailable"
19005
- ])
19006
- }).strict(),
19007
- completedAt: external_exports.string().nullable(),
19008
- coverageLimitations: external_exports.array(external_exports.string()).max(24),
19009
- /** @deprecated Use coverageLimitations. Retained for API compatibility. */
19010
- limitations: external_exports.array(external_exports.string()).max(24)
19011
- }).strict();
19012
19100
  var apiV2ScanFreshnessSchema = external_exports.enum(["latest", "refresh"]);
19013
19101
  var apiV2ScanFromSchema = external_exports.enum(["eu_de", "eu_ie", "california"]);
19014
19102
  var apiV2FindingCriticalitySchema = external_exports.enum(["critical", "high", "medium", "low", "info", "unknown"]);
@@ -19031,6 +19119,96 @@ var apiV2ScanCreationMetadataShape = {
19031
19119
  upgradeMessage: external_exports.string().nullable().optional(),
19032
19120
  recommendedNextTool: external_exports.enum(["certscore_get_scan_status", "certscore_get_scan_bundle"]).optional()
19033
19121
  };
19122
+ var apiV2PreConsentRuntimePreviewSchema = external_exports.object({
19123
+ type: external_exports.literal("certscore_pre_consent_preview"),
19124
+ resultStage: external_exports.literal("preliminary"),
19125
+ final: external_exports.literal(false),
19126
+ sourceLane: external_exports.literal("runtime_evidence"),
19127
+ generatedAt: external_exports.string().datetime(),
19128
+ runtimeCoverage: external_exports.object({
19129
+ status: external_exports.enum(["usable", "limited_partial", "limited_none", "not_applicable"]),
19130
+ limitationKeys: external_exports.array(external_exports.string().min(1).max(120)).max(16)
19131
+ }).strict(),
19132
+ summary: external_exports.object({
19133
+ cookieCount: external_exports.number().int().min(0),
19134
+ returnedCookieCount: external_exports.number().int().min(0).optional(),
19135
+ trackerCount: external_exports.number().int().min(0),
19136
+ trackingVendorCount: external_exports.number().int().min(0).optional(),
19137
+ returnedTrackingVendorCount: external_exports.number().int().min(0).optional(),
19138
+ operationalVendorCount: external_exports.number().int().min(0).optional(),
19139
+ returnedOperationalVendorCount: external_exports.number().int().min(0).optional(),
19140
+ thirdPartyRequestCount: external_exports.number().int().min(0),
19141
+ vendorCount: external_exports.number().int().min(0)
19142
+ }).strict(),
19143
+ cookies: external_exports.array(external_exports.object({
19144
+ name: external_exports.string().min(1).max(256),
19145
+ domain: external_exports.string().min(1).max(253).nullable(),
19146
+ party: external_exports.enum(["first_party", "third_party", "unknown"]),
19147
+ purpose: external_exports.enum([
19148
+ "analytics",
19149
+ "advertising",
19150
+ "marketing",
19151
+ "personalization",
19152
+ "session_replay",
19153
+ "consent_management",
19154
+ "tag_management",
19155
+ "infrastructure",
19156
+ "security",
19157
+ "performance_monitoring",
19158
+ "customer_support",
19159
+ "unknown"
19160
+ ]),
19161
+ essentiality: external_exports.enum(["essential", "non_essential", "unknown"]),
19162
+ observedAtMs: external_exports.number().int().min(0).nullable()
19163
+ }).strict()).max(20),
19164
+ trackers: external_exports.array(external_exports.object({
19165
+ vendor: external_exports.string().min(1).max(160),
19166
+ product: external_exports.string().min(1).max(160).nullable(),
19167
+ purpose: external_exports.enum([
19168
+ "analytics",
19169
+ "advertising",
19170
+ "marketing",
19171
+ "personalization",
19172
+ "session_replay",
19173
+ "consent_management",
19174
+ "tag_management",
19175
+ "infrastructure",
19176
+ "security",
19177
+ "performance_monitoring",
19178
+ "customer_support",
19179
+ "unknown"
19180
+ ]),
19181
+ confidence: external_exports.number().min(0).max(1),
19182
+ domains: external_exports.array(external_exports.string().min(1).max(253)).max(8)
19183
+ }).strict()).max(20),
19184
+ operationalVendors: external_exports.array(external_exports.object({
19185
+ vendor: external_exports.string().min(1).max(160),
19186
+ product: external_exports.string().min(1).max(160).nullable(),
19187
+ purpose: external_exports.enum([
19188
+ "analytics",
19189
+ "advertising",
19190
+ "marketing",
19191
+ "personalization",
19192
+ "session_replay",
19193
+ "consent_management",
19194
+ "tag_management",
19195
+ "infrastructure",
19196
+ "security",
19197
+ "performance_monitoring",
19198
+ "customer_support",
19199
+ "unknown"
19200
+ ]),
19201
+ confidence: external_exports.number().min(0).max(1),
19202
+ domains: external_exports.array(external_exports.string().min(1).max(253)).max(8)
19203
+ }).strict()).max(20).optional(),
19204
+ truncated: external_exports.object({
19205
+ cookies: external_exports.boolean(),
19206
+ trackers: external_exports.boolean(),
19207
+ operationalVendors: external_exports.boolean().optional()
19208
+ }).strict(),
19209
+ mustContinuePolling: external_exports.literal(true),
19210
+ observationOnlyDisclaimer: external_exports.string().min(1).max(500)
19211
+ }).strict();
19034
19212
  var apiV2LinksSchema = external_exports.object({
19035
19213
  self: external_exports.string().optional(),
19036
19214
  status: external_exports.string().optional(),
@@ -19044,6 +19222,7 @@ var apiV2ErrorSchema = external_exports.object({
19044
19222
  type: external_exports.literal("certscore_api_error"),
19045
19223
  error: external_exports.object({
19046
19224
  code: external_exports.enum(["invalid_request", "invalid_url", "not_found", "rate_limited", "unauthorized", "forbidden", "scan_unavailable", "internal_error"]),
19225
+ reasonCode: external_exports.enum(["non_public_target"]).nullable().optional(),
19047
19226
  message: external_exports.string(),
19048
19227
  retryable: external_exports.boolean(),
19049
19228
  retryAfterSeconds: external_exports.number().int().nullable(),
@@ -19099,7 +19278,10 @@ var apiV2ScanJobSchema = external_exports.object({
19099
19278
  scoreVersion: external_exports.string().nullable().optional(),
19100
19279
  scoreUpdatedAt: external_exports.string().nullable().optional(),
19101
19280
  riskLevel: external_exports.string().nullable().optional(),
19281
+ gpcResponse: apiV2GpcResponseSchema.nullable().optional(),
19282
+ postAcceptObservation: apiV2PostAcceptObservationSchema.nullable().optional(),
19102
19283
  postRefusalObservation: apiV2PostRefusalObservationSchema.nullable().optional(),
19284
+ preConsentPreview: apiV2PreConsentRuntimePreviewSchema.optional(),
19103
19285
  coverage: external_exports.object({
19104
19286
  status: external_exports.string().optional(),
19105
19287
  summary: external_exports.string().optional(),
@@ -19144,6 +19326,8 @@ var apiV2ScanResourceSchema = external_exports.object({
19144
19326
  scoreVersion: external_exports.string().nullable().optional(),
19145
19327
  scoreUpdatedAt: external_exports.string().nullable().optional(),
19146
19328
  riskLevel: external_exports.string().nullable().optional(),
19329
+ gpcResponse: apiV2GpcResponseSchema.nullable().optional(),
19330
+ postAcceptObservation: apiV2PostAcceptObservationSchema.nullable().optional(),
19147
19331
  postRefusalObservation: apiV2PostRefusalObservationSchema.nullable().optional(),
19148
19332
  coverage: external_exports.object({
19149
19333
  status: external_exports.string().optional(),
@@ -19386,6 +19570,14 @@ var apiV2PreConsentCookiesTrackersRowSchema = external_exports.object({
19386
19570
  var apiV2PreConsentCookiesTrackersSummarySchema = external_exports.object({
19387
19571
  rowCount: external_exports.number().int().min(0),
19388
19572
  trackerCount: external_exports.number().int().min(0),
19573
+ trackerCountScope: external_exports.literal("canonical_inventory_rows_including_operational").optional(),
19574
+ trackerCategoryCounts: external_exports.object({
19575
+ advertising: external_exports.number().int().min(0),
19576
+ analytics: external_exports.number().int().min(0),
19577
+ essential: external_exports.number().int().min(0),
19578
+ functional: external_exports.number().int().min(0),
19579
+ review: external_exports.number().int().min(0)
19580
+ }).strict().optional(),
19389
19581
  cookieCount: external_exports.number().int().min(0),
19390
19582
  requestCount: external_exports.number().int().min(0),
19391
19583
  vendorCount: external_exports.number().int().min(0).default(0),
@@ -19412,15 +19604,15 @@ var mcpCreateScanInputSchema = {
19412
19604
  url: external_exports.string().min(1).describe("Public URL or domain to scan."),
19413
19605
  detail: mcpPulseDetailSchema.optional().describe("Pulse detail level. Defaults to summary."),
19414
19606
  format: mcpPulseFormatSchema.optional().describe("Response format for completed immediate responses. Defaults to json."),
19415
- freshness: mcpPulseFreshnessSchema.optional().describe("Prefer latest for ordinary website checks so an eligible recent completed scan can be reused and new-scan allowance is not consumed unnecessarily; CertScore may still start a scan when no suitable result exists. Use refresh only when the user explicitly requests a fresh, new, or repeated scan; ordinary check, scan, audit, inspect, review, or assess wording alone does not request refresh."),
19416
- scanFrom: mcpScanFromSchema.optional().describe("Optional execution region for a newly queued scan. Omit when the user did not request a jurisdiction or regional perspective; use eu_de or eu_ie for explicit EU/GDPR/ePrivacy requests and california for explicit California/CCPA/CPRA requests. Do not use multiple regions unless comparison is requested, and do not infer EU from consent or California from a U.S. user location.")
19607
+ freshness: mcpPulseFreshnessSchema.optional().describe("Scan freshness policy. latest allows eligible recent completed-result reuse when available; refresh requests a new scan. Defaults to latest."),
19608
+ scanFrom: mcpScanFromSchema.optional().describe("Optional execution region for a newly queued scan: eu_de, eu_ie, california, or the service default when omitted.")
19417
19609
  };
19418
19610
  var mcpScanSiteInputSchema = {
19419
19611
  url: mcpCreateScanInputSchema.url,
19420
19612
  freshness: mcpCreateScanInputSchema.freshness,
19421
19613
  scanFrom: mcpCreateScanInputSchema.scanFrom,
19422
- waitForCompletion: external_exports.boolean().optional().describe("Wait for a completed scan resource within this tool call's wall-clock budget. Defaults to true. Set false only for an explicitly asynchronous workflow."),
19423
- maxWaitSeconds: external_exports.number().int().min(1).max(45).optional().describe("Total wall-clock budget for scan creation plus optional completion waiting. Defaults to 25 seconds. Creation time is deducted from polling; budget exhaustion returns the accepted active scan and stable scanId without an error.")
19614
+ waitForCompletion: external_exports.boolean().optional().describe("Deprecated compatibility field; accepted but ignored. certscore_scan_site never waits for a new scan to finish, though MCP Light may briefly wait within a bounded preview window for preliminary pre-consent observations."),
19615
+ maxWaitSeconds: external_exports.number().int().min(1).max(45).optional().describe("Deprecated compatibility field; accepted but ignored. The bounded preliminary-preview wait is controlled by CertScore and never waits for scan completion.")
19424
19616
  };
19425
19617
  var mcpGetScanStatusInputSchema = {
19426
19618
  scanId: external_exports.string().min(1).describe("Stable CertScore scan ID returned by certscore_scan_site.")
@@ -19627,7 +19819,11 @@ var mcpScanSiteOutputSchema = external_exports.object({
19627
19819
  scoreVersion: external_exports.string().nullable().optional(),
19628
19820
  scoreUpdatedAt: external_exports.string().nullable().optional(),
19629
19821
  riskLevel: external_exports.string().nullable().optional(),
19822
+ gpcResponse: apiV2ScanResourceSchema.shape.gpcResponse.nullable(),
19823
+ postAcceptObservation: apiV2ScanResourceSchema.shape.postAcceptObservation.nullable(),
19824
+ postRefusalObservation: apiV2ScanResourceSchema.shape.postRefusalObservation.nullable(),
19630
19825
  coverage: apiV2ScanResourceSchema.shape.coverage.nullable().optional(),
19826
+ preConsentPreview: apiV2PreConsentRuntimePreviewSchema.optional(),
19631
19827
  error: mcpActionableErrorSchema.nullable(),
19632
19828
  provenance: mcpScanProvenanceSchema,
19633
19829
  interpretationGuidance: mcpInterpretationGuidanceSchema,
@@ -19664,7 +19860,11 @@ var mcpScanStatusOutputSchema = external_exports.object({
19664
19860
  scoreVersion: external_exports.string().nullable().optional(),
19665
19861
  scoreUpdatedAt: external_exports.string().nullable().optional(),
19666
19862
  riskLevel: external_exports.string().nullable().optional(),
19863
+ gpcResponse: apiV2ScanResourceSchema.shape.gpcResponse.nullable(),
19864
+ postAcceptObservation: apiV2ScanResourceSchema.shape.postAcceptObservation.nullable(),
19865
+ postRefusalObservation: apiV2ScanResourceSchema.shape.postRefusalObservation.nullable(),
19667
19866
  coverage: apiV2ScanResourceSchema.shape.coverage.nullable().optional(),
19867
+ preConsentPreview: apiV2PreConsentRuntimePreviewSchema.optional(),
19668
19868
  phase: external_exports.string().optional(),
19669
19869
  phaseStartedAt: external_exports.string().nullable().optional(),
19670
19870
  lastUpdatedAt: external_exports.string().optional(),
@@ -19718,6 +19918,8 @@ var mcpScanBundleOutputSchema = external_exports.object({
19718
19918
  scoreVersion: external_exports.string().nullable(),
19719
19919
  scoreUpdatedAt: external_exports.string().nullable(),
19720
19920
  riskLevel: external_exports.string().nullable(),
19921
+ gpcResponse: apiV2ScanResourceSchema.shape.gpcResponse.nullable().optional(),
19922
+ postAcceptObservation: apiV2ScanResourceSchema.shape.postAcceptObservation.nullable(),
19721
19923
  postRefusalObservation: apiV2ScanResourceSchema.shape.postRefusalObservation.nullable(),
19722
19924
  provenance: mcpScanProvenanceSchema,
19723
19925
  interpretationGuidance: mcpInterpretationGuidanceSchema,
@@ -19830,10 +20032,10 @@ var certScoreMcpToolContracts = [
19830
20032
  {
19831
20033
  name: "certscore_scan_site",
19832
20034
  title: "Scan site",
19833
- description: "Use CertScore.ai to scan a public website for observable privacy and consent signals, including pre-consent cookies and browser storage, third-party trackers, consent-banner and CMP behavior, TLS/transport security, privacy-policy disclosures, GDPR/ePrivacy transparency findings, and applicable CCPA/CPRA review signals. Starts or reuses a public-web scan with a 25-second total tool-call budget by default; scan creation time is deducted from completion waiting. If status is queued, running, or finalizing, retain scanId and poll certscore_get_scan_status using only that scanId. Stop polling at completed, completed_limited, failed, expired, or rate_limited. For usable completion, call certscore_get_scan_bundle. No-go and limited coverage are observations, never proof of compliance.",
20035
+ description: "Creates a public-website privacy scan or reuses an eligible recent completed scan. Coverage includes pre-consent storage, trackers, consent and CMP signals, privacy-policy disclosures, transport security, and GDPR/ePrivacy or CCPA/CPRA review signals. The response contains a stable scanId, lifecycle status, retry timing, and sometimes a bounded preliminary preConsentPreview; preliminary data contains no final findings or score. Results are automated public-web observations, not legal advice, certification, or a compliance determination. Tool and workflow documentation: https://certscore.ai/developers/mcp.",
19834
20036
  inputSchema: mcpScanSiteInputSchema,
19835
20037
  outputSchema: mcpScanSiteOutputSchema,
19836
- annotations: scanCreationAnnotations
20038
+ annotations: { title: "Scan site", ...scanCreationAnnotations }
19837
20039
  },
19838
20040
  {
19839
20041
  name: "certscore_get_scan",
@@ -19841,15 +20043,15 @@ var certScoreMcpToolContracts = [
19841
20043
  description: "Retrieve the API v2 public-safe scan resource, including completed-limited no-go disposition, reason-specific guidance, and timing when available.",
19842
20044
  inputSchema: mcpGetScanInputSchema,
19843
20045
  outputSchema: apiV2ScanResourceSchema,
19844
- annotations: readOnlyOpenWorldAnnotations
20046
+ annotations: { title: "Get CertScore scan", ...readOnlyOpenWorldAnnotations }
19845
20047
  },
19846
20048
  {
19847
20049
  name: "certscore_get_scan_status",
19848
20050
  title: "Get scan status",
19849
- description: "Poll with only the stable scanId returned by certscore_scan_site. Active responses include phase, heartbeat, estimated progress, stalled state, retry delay, and canonical scan provenance when available. Terminal responses include the CertScore score, risk, coverage, execution region (scanFrom), timestamps, report URL, and an explicit next action. For a reused or retrieved existing scan, use only persisted scanFrom and timestamps; never infer its original region from the current request, the user's location, or a default. Report unavailable provenance as unavailable. Stop polling at any terminal status.",
20051
+ description: "Returns lifecycle status for a stable CertScore scanId. Active responses include phase, heartbeat, estimated progress, retryAfterSeconds, and sometimes a bounded preliminary preConsentPreview. Terminal responses include completion status, CertScore score and risk metadata when available, coverage, persisted execution region and timestamps, report URL, and a next-action field. Preliminary observations are distinct from completed findings.",
19850
20052
  inputSchema: mcpGetScanStatusInputSchema,
19851
20053
  outputSchema: mcpScanStatusOutputSchema,
19852
- annotations: readOnlyInternalAnnotations
20054
+ annotations: { title: "Get scan status", ...readOnlyInternalAnnotations }
19853
20055
  },
19854
20056
  {
19855
20057
  name: "certscore_get_report",
@@ -19857,7 +20059,7 @@ var certScoreMcpToolContracts = [
19857
20059
  description: "Focused follow-up: retrieve a bounded Pulse report with high-signal TextContent and typed structuredContent, including customer-safe no-go messaging. For broad privacy questions, use certscore_get_scan_bundle first because it combines canonical findings, limitations, and pre-consent rows without redundant calls.",
19858
20060
  inputSchema: mcpGetReportInputSchema,
19859
20061
  outputSchema: mcpReportOutputSchema,
19860
- annotations: readOnlyOpenWorldAnnotations
20062
+ annotations: { title: "Get CertScore Pulse report", ...readOnlyOpenWorldAnnotations }
19861
20063
  },
19862
20064
  {
19863
20065
  name: "certscore_get_evidence",
@@ -19865,15 +20067,15 @@ var certScoreMcpToolContracts = [
19865
20067
  description: "Focused follow-up: retrieve a bounded public-safe evidence packet with a concise TextContent digest and typed structuredContent. For broad privacy questions, use certscore_get_scan_bundle first. Excludes raw cookie values, raw bodies, sensitive payloads, full DOM, and unredacted query values.",
19866
20068
  inputSchema: mcpGetEvidenceInputSchema,
19867
20069
  outputSchema: mcpEvidenceOutputSchema,
19868
- annotations: readOnlyOpenWorldAnnotations
20070
+ annotations: { title: "Get CertScore Pulse evidence", ...readOnlyOpenWorldAnnotations }
19869
20071
  },
19870
20072
  {
19871
20073
  name: "certscore_get_scan_bundle",
19872
20074
  title: "Get scan bundle",
19873
- description: "Call after completed or completed_limited status. Every usable completed bundle returns a self-contained concise TextContent digest plus matching structuredContent, including canonical execution region (scanFrom) and timestamps when available. For a reused or retrieved existing scan, use only persisted scanFrom and timestamps; never infer its original region from the current request, the user's location, or a default, and report unavailable provenance as unavailable. The default summary includes the canonical report overview, up to five compact public-safe projected findings across the scan's observed domains, and bounded row-level pre-consent cookie/tracker evidence; detail=findings increases the default finding allowance, evidence adds bounded evidence digests and references, and full adds all available bounded sections. MCP Light applies a 25000-byte response ceiling so full results remain transport-safe; use returned content URLs when the complete requested tier exceeds it. At the 5000-byte floor, core finding rows take priority over optional inventory and duplicate envelope fields; evidenceUrlTemplate may replace repeated per-finding URLs while preserving their canonical derivation from contentUrls.findings and findingId. Every response declares finding and evidence total/returned/truncated counts, canonicalFindingsComplete, requested and effective byte budgets, the response ceiling, omittedSections, retrieval URLs, and nextRecommendedMaxBytes when the complete tier fits the ceiling. When canonicalFindingsComplete is true, retry only if omitted envelope detail is needed. Enumerate only returned observations and projected findings. Post-refusal observation may intentionally stop as soon as qualifying non-essential activity or a retained consent-signal contradiction is observed. A confirmed observation with termination.kind=evidence_satisfied is positive evidence for the returned observation, not an inconclusive Reject Path result; keep any coverageLimitations scoped to additional behavior or persistence that was not measured. Treat criticality, priority, and confidence as CertScore metadata; regulatory review lenses are non-determinative CertScore review context, not legal severity, legal exposure, or a compliance determination. Missing consent-action evidence does not establish Accept, Reject, or Decline behavior. Do not extrapolate observed embeds, vendors, or requests into unobserved cookies, fingerprinting, tracking, or processing. The CertScore score covers observable scan signals only; do not infer unobserved technologies or legal compliance status, and never interpret no-go, not-observed, or limited coverage as proof of compliance.",
20075
+ description: "Returns the completed or completed-limited CertScore evidence bundle for a stable scanId as concise TextContent and matching structuredContent. Available sections include the canonical report overview, bounded projected findings, pre-consent cookie and tracker evidence, coverage limitations, persisted execution provenance, and retrieval URLs. Detail tiers and byte budgets control the bounded response, with explicit returned, total, truncated, and omitted-section metadata. Accept and Reject Path content is present only for confirmed, evidence-qualified post-action observations; unsupported or inconclusive outcomes remain neutral coverage limitations. Results are automated public-web observations, not legal advice, certification, or a compliance determination.",
19874
20076
  inputSchema: mcpGetScanBundleInputSchema,
19875
20077
  outputSchema: mcpScanBundleOutputSchema,
19876
- annotations: accountedInternalReadAnnotations
20078
+ annotations: { title: "Get scan bundle", ...accountedInternalReadAnnotations }
19877
20079
  },
19878
20080
  {
19879
20081
  name: "certscore_export_findings",
@@ -19881,7 +20083,7 @@ var certScoreMcpToolContracts = [
19881
20083
  description: "Return structured findings plus completed-limited no-go disposition and guidance for downstream review or ticketing workflows.",
19882
20084
  inputSchema: mcpExportFindingsInputSchema,
19883
20085
  outputSchema: mcpFindingsExportOutputSchema,
19884
- annotations: readOnlyOpenWorldAnnotations
20086
+ annotations: { title: "Export CertScore findings", ...readOnlyOpenWorldAnnotations }
19885
20087
  },
19886
20088
  {
19887
20089
  name: "certscore_list_findings",
@@ -19889,7 +20091,7 @@ var certScoreMcpToolContracts = [
19889
20091
  description: "Focused follow-up: list bounded API v2 public-safe findings already projected by the canonical pipeline, with matching high-signal TextContent and typed structuredContent. For broad privacy questions, use certscore_get_scan_bundle first.",
19890
20092
  inputSchema: mcpListFindingsInputSchema,
19891
20093
  outputSchema: mcpFindingListOutputSchema,
19892
- annotations: readOnlyOpenWorldAnnotations
20094
+ annotations: { title: "List CertScore findings", ...readOnlyOpenWorldAnnotations }
19893
20095
  },
19894
20096
  {
19895
20097
  name: "certscore_get_pre_consent_cookies_trackers",
@@ -19897,7 +20099,7 @@ var certScoreMcpToolContracts = [
19897
20099
  description: "Focused follow-up: retrieve bounded row-level public-safe pre-consent cookie/tracker evidence with matching TextContent and typed structuredContent. For a new broad request such as checking a site for pre-consent tracking, use certscore_scan_site then certscore_get_scan_bundle first.",
19898
20100
  inputSchema: mcpGetPreConsentCookiesTrackersInputSchema,
19899
20101
  outputSchema: mcpPreConsentCookiesTrackersOutputSchema,
19900
- annotations: readOnlyOpenWorldAnnotations
20102
+ annotations: { title: "Get pre-consent cookies and trackers", ...readOnlyOpenWorldAnnotations }
19901
20103
  },
19902
20104
  {
19903
20105
  name: "certscore_explain_finding",
@@ -19905,7 +20107,7 @@ var certScoreMcpToolContracts = [
19905
20107
  description: "Explain one projected finding with public evidence, caveats, reviewer next steps, and reason-specific no-go context when applicable.",
19906
20108
  inputSchema: mcpExplainFindingInputSchema,
19907
20109
  outputSchema: apiV2FindingDetailSchema,
19908
- annotations: readOnlyOpenWorldAnnotations
20110
+ annotations: { title: "Explain CertScore finding", ...readOnlyOpenWorldAnnotations }
19909
20111
  },
19910
20112
  {
19911
20113
  name: "certscore_get_latest_domain_scan",
@@ -19913,7 +20115,7 @@ var certScoreMcpToolContracts = [
19913
20115
  description: "Retrieve the latest eligible API v2 public-safe scan for a domain.",
19914
20116
  inputSchema: mcpGetLatestDomainScanInputSchema,
19915
20117
  outputSchema: apiV2DomainLatestScanSchema,
19916
- annotations: readOnlyOpenWorldAnnotations
20118
+ annotations: { title: "Get latest domain scan", ...readOnlyOpenWorldAnnotations }
19917
20119
  },
19918
20120
  {
19919
20121
  name: "certscore_get_latest_domain_pre_consent_cookies_trackers",
@@ -19921,7 +20123,7 @@ var certScoreMcpToolContracts = [
19921
20123
  description: "Focused follow-up: retrieve bounded row-level public-safe pre-consent cookie/tracker evidence from the latest eligible scan for a domain, with matching TextContent and typed structuredContent. For a broad current-site review, use certscore_scan_site then certscore_get_scan_bundle first.",
19922
20124
  inputSchema: mcpGetLatestDomainPreConsentCookiesTrackersInputSchema,
19923
20125
  outputSchema: mcpPreConsentCookiesTrackersOutputSchema,
19924
- annotations: readOnlyOpenWorldAnnotations
20126
+ annotations: { title: "Get latest domain pre-consent cookies and trackers", ...readOnlyOpenWorldAnnotations }
19925
20127
  }
19926
20128
  ];
19927
20129
 
@@ -19941,6 +20143,8 @@ var preConsentCookiesTrackersExample = {
19941
20143
  summary: {
19942
20144
  rowCount: 2,
19943
20145
  trackerCount: 1,
20146
+ trackerCountScope: "canonical_inventory_rows_including_operational",
20147
+ trackerCategoryCounts: { advertising: 0, analytics: 1, essential: 0, functional: 0, review: 0 },
19944
20148
  cookieCount: 1,
19945
20149
  requestCount: 3
19946
20150
  },
@@ -19995,7 +20199,14 @@ var preConsentCookiesTrackersExample = {
19995
20199
  };
19996
20200
  var emptyPreConsentCookiesTrackersExample = {
19997
20201
  ...preConsentCookiesTrackersExample,
19998
- summary: { rowCount: 0, trackerCount: 0, cookieCount: 0, requestCount: 0 },
20202
+ summary: {
20203
+ rowCount: 0,
20204
+ trackerCount: 0,
20205
+ trackerCountScope: "canonical_inventory_rows_including_operational",
20206
+ trackerCategoryCounts: { advertising: 0, analytics: 0, essential: 0, functional: 0, review: 0 },
20207
+ cookieCount: 0,
20208
+ requestCount: 0
20209
+ },
19999
20210
  rows: []
20000
20211
  };
20001
20212
  var errorContent = {
@@ -31875,11 +32086,14 @@ var MAX_TOOL_TEXT_CHARS = 8e3;
31875
32086
  var LEGAL_REVIEW_DISCLAIMER = "CertScore results are automated public-web observations for human and agentic review, not legal advice, certification, or a compliance determination.";
31876
32087
  var SCAN_PROVENANCE_GROUNDING = "retrievalMode describes how the current tool response obtained the scan; creationDecision describes whether the original scan request created or reused a scan only when that decision is retained. Never infer an unknown creationDecision from scan_id_lookup. For a reused or retrieved existing scan, use only persisted scanFrom and timestamps. Never infer its original scan region from the current request, the user's location, or a default execution region. If persisted region or timestamps are unavailable, report them as unavailable.";
31877
32088
  var INTERPRETATION_STATEMENT = "The CertScore score covers observable public-web scan signals only. Do not infer technologies that are not listed in the returned evidence or any legal compliance status.";
31878
- var SCAN_BUNDLE_RESPONSE_CONTRACT = `Response contract: Report only observed CertScore evidence and CertScore classifications. criticality, priority, and confidence are CertScore metadata; regulatory review lenses are non-determinative CertScore review context\u2014not legal severity, legal exposure, or a compliance determination. Absence of captured consent-action evidence does not establish what happens after Accept, Reject, or Decline. A confirmed post-refusal observation with termination.kind=evidence_satisfied means the observer intentionally stopped after retaining qualifying evidence; do not treat that termination as uncertainty about the returned observation. Keep any separately returned coverage limitation scoped to what was not measured. Do not extrapolate an observed embed, vendor, or request into unobserved cookies, fingerprinting, tracking, or processing, and do not infer violations or compliance beyond what CertScore observed. ${SCAN_PROVENANCE_GROUNDING}`;
31879
- var SCAN_BUNDLE_INTERPRETATION_STATEMENT = "Report only observed CertScore evidence and persisted CertScore classifications. Without corresponding captured post-action evidence, do not infer what Accept, Reject, Decline, or another consent action would do; say the scan does not establish what happens after that action. When postRefusalObservation is confirmed and termination.kind is evidence_satisfied, state the returned post-refusal observation directly and explain that observation stopped intentionally after qualifying evidence was retained. Do not characterize that termination as uncertainty about the observation; mention unmeasured longer-term persistence only when relevant. Do not speculate that an observed embed, vendor, or request may cause additional cookies, fingerprinting, tracking, or processing unless CertScore observed that behavior. Treat returned priority or severity as a CertScore classification, not regulatory criticality or legal exposure; prefer \u2018observed privacy risk signal\u2019 or \u2018CertScore finding\u2019. Do not infer unobserved technologies, legal compliance, or a legal violation from scores or findings.";
32089
+ var SCAN_BUNDLE_RESPONSE_CONTRACT = `Response contract: Report only observed CertScore evidence and CertScore classifications. criticality, priority, and confidence are CertScore metadata; regulatory review lenses are non-determinative CertScore review context\u2014not legal severity, legal exposure, or a compliance determination. Absence of captured consent-action evidence does not establish what happens after Accept, Reject, or Decline. A confirmed post-action observation with termination.kind=evidence_satisfied means the observer intentionally stopped after retaining qualifying evidence; do not treat that termination as uncertainty about the returned observation. Keep any separately returned coverage limitation scoped to what was not measured. Do not extrapolate an observed embed, vendor, or request into unobserved cookies, fingerprinting, tracking, or processing, and do not infer violations or compliance beyond what CertScore observed. ${SCAN_PROVENANCE_GROUNDING}`;
32090
+ var SCAN_BUNDLE_INTERPRETATION_STATEMENT = "Report only observed CertScore evidence and persisted CertScore classifications. For gpcResponse, use only GPC response, No observable GPC response, or indeterminate; do not call the result a GPC violation or say GPC was not honored. Keep its jurisdiction-neutral comparison separate from any explicitly returned California scoring policy. Without corresponding captured post-action evidence, do not infer what Accept, Reject, Decline, or another consent action would do; say the scan does not establish what happens after that action. When postAcceptObservation or postRefusalObservation is confirmed and termination.kind is evidence_satisfied, state the returned observation directly and explain that observation stopped intentionally after qualifying evidence was retained. Do not characterize that termination as uncertainty about the observation; mention unmeasured longer-term persistence only when relevant. Treat post-Accept activity as a score-neutral behavior baseline unless a separately projected finding says otherwise. Do not speculate that an observed embed, vendor, or request may cause additional cookies, fingerprinting, tracking, or processing unless CertScore observed that behavior. Treat returned priority or severity as a CertScore classification, not regulatory criticality or legal exposure; prefer \u2018observed privacy risk signal\u2019 or \u2018CertScore finding\u2019. Do not infer unobserved technologies, legal compliance, or a legal violation from scores or findings.";
31880
32091
  var COMPACT_SCAN_BUNDLE_INTERPRETATION_STATEMENT = "Use only returned CertScore observations and classifications. Do not infer unobserved technologies, post-consent behavior, legal compliance, or violations. Treat priority and severity as CertScore metadata.";
31881
32092
  var OBSERVATION_ONLY_DISCLAIMER = `${LEGAL_REVIEW_DISCLAIMER} No-go, not-observed, and limited-coverage results are not proof of compliance.`;
31882
32093
  var COMPACT_OBSERVATION_ONLY_DISCLAIMER = "Automated public-web observation, not legal advice or a compliance determination; missing or limited evidence is not proof of compliance.";
32094
+ var MCP_SCAN_CREATION_POLL_DELAY_SECONDS = 15;
32095
+ var MCP_QUEUED_POLL_DELAY_SECONDS = 10;
32096
+ var MCP_RUNNING_POLL_DELAY_SECONDS = 5;
31883
32097
  function interpretationGuidance(statement = INTERPRETATION_STATEMENT) {
31884
32098
  return {
31885
32099
  scoreLabel: "CertScore score",
@@ -31898,6 +32112,9 @@ function toolResultSummary(payload) {
31898
32112
  const status = typeof record2.status === "string" ? `; status=${record2.status}` : "";
31899
32113
  const scanId = typeof record2.scanId === "string" ? `; scanId=${record2.scanId}` : "";
31900
32114
  const score = typeof record2.score === "number" ? `; CertScore score=${record2.score}` : "";
32115
+ const preview = record2.preConsentPreview && typeof record2.preConsentPreview === "object" && !Array.isArray(record2.preConsentPreview) ? record2.preConsentPreview : null;
32116
+ const previewSummary = preview?.summary && typeof preview.summary === "object" && !Array.isArray(preview.summary) ? preview.summary : null;
32117
+ const preliminary = preview ? `; preliminary pre-consent preview=cookies ${previewSummary?.cookieCount ?? "unknown"}, trackers ${previewSummary?.trackerCount ?? "unknown"}, third-party requests ${previewSummary?.thirdPartyRequestCount ?? "unknown"}; preview is not final\u2014continue status polling` : "";
31901
32118
  const recordLinks = record2.links && typeof record2.links === "object" && !Array.isArray(record2.links) ? record2.links : null;
31902
32119
  const reportUrl = typeof record2.reportUrl === "string" && record2.reportUrl.trim() ? record2.reportUrl.trim() : typeof recordLinks?.report === "string" && recordLinks.report.trim() ? recordLinks.report.trim() : null;
31903
32120
  const report = reportUrl ? `; full report=${reportUrl}` : "";
@@ -31905,7 +32122,7 @@ function toolResultSummary(payload) {
31905
32122
  const retrieval = typeof provenanceRecord?.retrievalMode === "string" ? `; retrieval=${provenanceRecord.retrievalMode}` : "";
31906
32123
  const creation = typeof provenanceRecord?.creationDecision === "string" ? `; creation=${provenanceRecord.creationDecision}` : "";
31907
32124
  const provenance = retrieval || creation ? `${retrieval}${creation}` : typeof provenanceRecord?.mode === "string" ? `; provenance=${provenanceRecord.mode}` : "";
31908
- return `CertScore ${type}${status}${scanId}${score}${provenance}${report}. Full result is in structuredContent.`;
32125
+ return `CertScore ${type}${status}${scanId}${score}${preliminary}${provenance}${report}. Full result is in structuredContent.`;
31909
32126
  }
31910
32127
  function toToolResult(payload, text) {
31911
32128
  const structuredContent = payload !== null && typeof payload === "object" && !Array.isArray(payload) ? payload : { value: payload };
@@ -31926,12 +32143,14 @@ function toToolError(error2) {
31926
32143
  const retryable = typeof terminalError?.retryable === "boolean" ? terminalError.retryable : status === 429 || typeof status === "number" && status >= 500;
31927
32144
  const retryAfterSeconds = typeof terminalError?.retryAfterSeconds === "number" ? terminalError.retryAfterSeconds : error2 instanceof CertScoreError && "retryAfterSeconds" in error2 && typeof error2.retryAfterSeconds === "number" ? error2.retryAfterSeconds : retryable ? 30 : null;
31928
32145
  const code = error2 instanceof CertScoreError ? error2.code : "internal_error";
32146
+ const reasonCode = terminalError?.reasonCode === "non_public_target" ? "non_public_target" : null;
31929
32147
  const message = error2 instanceof Error ? error2.message : "Unknown CertScore MCP error.";
31930
32148
  const creationRateLimit = terminalError?.creationRateLimit && typeof terminalError.creationRateLimit === "object" && !Array.isArray(terminalError.creationRateLimit) ? terminalError.creationRateLimit : null;
31931
32149
  const recommendedNextAction = typeof terminalError?.recommendedNextAction === "string" ? terminalError.recommendedNextAction : creationRateLimit ? `No scan was created. Wait ${retryAfterSeconds ?? 30} seconds, then retry the same request. If the limit continues after that delay, contact support@certscore.ai.` : retryable ? `Wait ${retryAfterSeconds ?? 30} seconds, then retry the same request. Stop and contact support@certscore.ai if the error repeats.` : "Correct the request using the error details, then retry only if the requested operation is still appropriate.";
31932
32150
  const payload = {
31933
32151
  error: {
31934
32152
  code,
32153
+ reasonCode,
31935
32154
  message,
31936
32155
  retryable,
31937
32156
  retryAfterSeconds,
@@ -32063,27 +32282,36 @@ function scanProvenance(value, fallbackMode) {
32063
32282
  freshnessDecision: typeof value.freshnessDecision === "string" ? value.freshnessDecision : null
32064
32283
  };
32065
32284
  }
32066
- function withMcpAgentGuidance(value, fallbackProvenanceMode = "unknown") {
32285
+ function withMcpAgentGuidance(value, fallbackProvenanceMode = "unknown", pollGuidanceContext = "upstream") {
32067
32286
  const status = String(value.status ?? "");
32068
32287
  const active = status === "queued" || status === "running" || status === "finalizing";
32069
32288
  const usable = status === "completed" || status === "completed_limited";
32289
+ const upstreamRetryAfterSeconds = typeof value.retryAfterSeconds === "number" && Number.isFinite(value.retryAfterSeconds) ? Math.max(1, Math.ceil(value.retryAfterSeconds)) : null;
32290
+ const retryAfterSeconds = active && pollGuidanceContext === "scan_creation" ? MCP_SCAN_CREATION_POLL_DELAY_SECONDS : active && pollGuidanceContext === "scan_status" ? status === "queued" ? MCP_QUEUED_POLL_DELAY_SECONDS : MCP_RUNNING_POLL_DELAY_SECONDS : upstreamRetryAfterSeconds;
32070
32291
  const error2 = terminalErrorForResult(value);
32071
32292
  const stableScanId = typeof value.scanId === "string" && value.scanId.trim() ? value.scanId.trim() : typeof value.scan_id === "string" && value.scan_id.trim() ? value.scan_id.trim() : null;
32293
+ const hasPreConsentPreview2 = Boolean(
32294
+ value.preConsentPreview && typeof value.preConsentPreview === "object" && !Array.isArray(value.preConsentPreview)
32295
+ );
32072
32296
  const reportUrl = usable ? typeof value.reportUrl === "string" && value.reportUrl.trim() ? value.reportUrl.trim() : typeof value.links?.report === "string" && value.links.report.trim() ? value.links.report.trim() : stableScanId ? `https://certscore.ai/scan/${encodeURIComponent(stableScanId)}` : null : null;
32297
+ const returnedNextAction = typeof value.recommendedNextAction === "string" && value.recommendedNextAction.trim() ? value.recommendedNextAction.trim() : null;
32298
+ const activePollAction = `${retryAfterSeconds === null ? "Wait for the recommended delay" : `Wait at least ${retryAfterSeconds} seconds`}, then call certscore_get_scan_status once with scanId ${stableScanId ?? value.jobId}.`;
32299
+ const activeNextAction = `${hasPreConsentPreview2 ? "The returned preConsentPreview is a partial preview of passive evidence. Its counts are checkpoint-only partial counts, not the full scan tally; do not present them as final totals or stop the workflow. " : ""}${activePollAction} Continue with certscore_get_scan_status using the unchanged scanId ${stableScanId ?? value.jobId}. Do not poll in parallel or resubmit certscore_scan_site while this scan is active. After completed or completed_limited, call certscore_get_scan_bundle for the completed scan's final returned tally, canonical findings, and limitations.`;
32073
32300
  return {
32074
32301
  ...value,
32302
+ retryAfterSeconds,
32075
32303
  error: error2,
32076
32304
  reportUrl,
32077
32305
  scoreLabel: "CertScore score",
32078
32306
  provenance: scanProvenance(value, fallbackProvenanceMode),
32079
32307
  interpretationGuidance: interpretationGuidance(),
32080
32308
  recommendedNextTool: active ? "certscore_get_scan_status" : usable ? "certscore_get_scan_bundle" : null,
32081
- recommendedNextAction: error2?.recommendedNextAction ?? value.recommendedNextAction ?? (active ? `Poll certscore_get_scan_status with scanId ${value.scanId ?? value.jobId} after the recommended delay.` : usable ? `Call certscore_get_scan_bundle with scanId ${value.scanId ?? value.jobId} for the canonical findings and limitations.` : "Review the result and retained limitations."),
32309
+ recommendedNextAction: error2?.recommendedNextAction ?? (active ? activeNextAction : returnedNextAction ?? (usable ? `Call certscore_get_scan_bundle with scanId ${stableScanId ?? value.jobId} for the completed scan's final returned tally, canonical findings, and limitations.` : "Review the result and retained limitations.")),
32082
32310
  observationOnlyDisclaimer: OBSERVATION_ONLY_DISCLAIMER
32083
32311
  };
32084
32312
  }
32085
32313
  function withMcpScanProvenanceGuidance(value, fallbackProvenanceMode) {
32086
- const guided = withMcpAgentGuidance(value, fallbackProvenanceMode);
32314
+ const guided = withMcpAgentGuidance(value, fallbackProvenanceMode, "scan_status");
32087
32315
  return {
32088
32316
  ...guided,
32089
32317
  interpretationGuidance: interpretationGuidance(`${INTERPRETATION_STATEMENT} ${SCAN_PROVENANCE_GROUNDING}`)
@@ -32657,14 +32885,124 @@ function canonicalScanProvenanceText(value) {
32657
32885
  }
32658
32886
  function scanStatusText(value) {
32659
32887
  const reportUrl = reportUrlFor(value);
32660
- return [
32661
- `CertScore scan status: status=${value.status ?? "unknown"}.`,
32888
+ const nextAction = typeof value.recommendedNextAction === "string" && value.recommendedNextAction.trim() ? value.recommendedNextAction.trim() : "Review the returned status and retained limitations.";
32889
+ return boundedPreviewResultText([
32890
+ `CertScore scan status: status=${value.status ?? "unknown"}.`
32891
+ ], [...preConsentPreviewTextLines(value), ...terminalLaneResultTextLines(value)], [
32892
+ `Next: ${nextAction}`,
32662
32893
  canonicalScanProvenanceText(value),
32663
32894
  `Full report: ${reportUrl ?? "not available"}.`,
32664
32895
  OBSERVATION_ONLY_DISCLAIMER,
32665
32896
  INTERPRETATION_STATEMENT,
32666
32897
  SCAN_PROVENANCE_GROUNDING
32667
- ].join("\n");
32898
+ ]);
32899
+ }
32900
+ function scanSiteText(value, leadingLines = []) {
32901
+ const scanId = extractScanId(value) ?? "unknown";
32902
+ const active = value.status === "queued" || value.status === "running" || value.status === "finalizing";
32903
+ const nextAction = typeof value.recommendedNextAction === "string" && value.recommendedNextAction.trim() ? value.recommendedNextAction.trim() : active ? `Call certscore_get_scan_status sequentially with scanId ${scanId}; do not resubmit certscore_scan_site.` : "Review the returned result and retained limitations.";
32904
+ return boundedPreviewResultText([
32905
+ ...leadingLines,
32906
+ `CertScore scan accepted: scanId=${scanId}; status=${value.status ?? "unknown"}.`
32907
+ ], [...preConsentPreviewTextLines(value), ...terminalLaneResultTextLines(value)], [
32908
+ `Next: ${nextAction}`,
32909
+ `Provenance: retrieval=${value.provenance?.retrievalMode ?? "unknown"}; creation=${value.provenance?.creationDecision ?? "unknown"}.`,
32910
+ canonicalScanProvenanceText(value),
32911
+ OBSERVATION_ONLY_DISCLAIMER,
32912
+ INTERPRETATION_STATEMENT
32913
+ ]);
32914
+ }
32915
+ function terminalLaneResultTextLines(value) {
32916
+ const lines = [];
32917
+ const gpcResponse = value.gpcResponse && typeof value.gpcResponse === "object" && !Array.isArray(value.gpcResponse) ? value.gpcResponse : null;
32918
+ if (gpcResponse) {
32919
+ lines.push(`GPC response: ${gpcResponse.findingTitle ?? "GPC response"}; status=${gpcResponse.status ?? "indeterminate"}; Sec-GPC: 1 proof retained on ${gpcResponse.comparison?.enabledProof?.requestsWithSecGpc ?? 0} request(s).`);
32920
+ }
32921
+ for (const [field, label] of [["postAcceptObservation", "Accept Path"], ["postRefusalObservation", "Reject Path"]]) {
32922
+ const observation = value[field] && typeof value[field] === "object" && !Array.isArray(value[field]) ? value[field] : null;
32923
+ if (observation && typeof observation.interpretation === "string") {
32924
+ lines.push(`${label}: ${observation.interpretation}`);
32925
+ }
32926
+ }
32927
+ return lines;
32928
+ }
32929
+ function compactPreviewValue(value, fallback = "unknown", maxChars = 280) {
32930
+ if (value === null || value === void 0) return fallback;
32931
+ const normalized = String(value).replace(/\s+/g, " ").trim();
32932
+ if (!normalized) return fallback;
32933
+ return normalized.length > maxChars ? `${normalized.slice(0, Math.max(1, maxChars - 1))}\u2026` : normalized;
32934
+ }
32935
+ function previewObservedTiming(value) {
32936
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? `${Math.round(value)}ms (t+${(value / 1e3).toFixed(3)}s)` : "unavailable";
32937
+ }
32938
+ function preConsentPreviewTextLines(value) {
32939
+ const preview = value.preConsentPreview && typeof value.preConsentPreview === "object" && !Array.isArray(value.preConsentPreview) ? value.preConsentPreview : null;
32940
+ if (!preview) return [];
32941
+ const cookies = Array.isArray(preview.cookies) ? preview.cookies : [];
32942
+ const trackers = Array.isArray(preview.trackers) ? preview.trackers : [];
32943
+ const operationalVendors = Array.isArray(preview.operationalVendors) ? preview.operationalVendors : [];
32944
+ const summary = preview.summary && typeof preview.summary === "object" && !Array.isArray(preview.summary) ? preview.summary : {};
32945
+ const coverage = preview.runtimeCoverage && typeof preview.runtimeCoverage === "object" && !Array.isArray(preview.runtimeCoverage) ? preview.runtimeCoverage : {};
32946
+ const capturedCookieCount = summary.cookieCount ?? cookies.length;
32947
+ const returnedCookieCount = summary.returnedCookieCount ?? cookies.length;
32948
+ const capturedTrackingVendorCount = summary.trackingVendorCount ?? summary.trackerCount ?? trackers.length;
32949
+ const returnedTrackingVendorCount = summary.returnedTrackingVendorCount ?? trackers.length;
32950
+ const capturedOperationalVendorCount = summary.operationalVendorCount ?? operationalVendors.length;
32951
+ const returnedOperationalVendorCount = summary.returnedOperationalVendorCount ?? operationalVendors.length;
32952
+ const lines = [
32953
+ `Partial pre-consent runtime preview: generated=${compactPreviewValue(preview.generatedAt, "unavailable", 80)}; lane=${compactPreviewValue(preview.sourceLane, "runtime_evidence", 80)}; coverage=${compactPreviewValue(coverage.status, "unknown", 80)}; cookies captured=${capturedCookieCount}; cookie identities returned=${returnedCookieCount}; tracking vendors captured=${capturedTrackingVendorCount}; tracking vendor identities returned=${returnedTrackingVendorCount}; operational/security/consent vendors captured=${capturedOperationalVendorCount}; operational identities returned=${returnedOperationalVendorCount}; all classified vendor observations=${summary.vendorCount ?? "unknown"}; third-party requests=${summary.thirdPartyRequestCount ?? "unknown"}.`,
32954
+ "PARTIAL PREVIEW: These are checkpoint-only partial counts, not the full scan tally. Do not present them as final totals or stop the workflow. Wait for terminal scan status, then call certscore_get_scan_bundle for the completed scan's final returned tally, canonical findings, and coverage limitations.",
32955
+ "Metric scope: tracking vendors exclude operational, security, and consent-management vendors. The completed inventory's broader trackerCount may include those categories, so do not compare that field directly with trackingVendorCount."
32956
+ ];
32957
+ if (cookies.length > 0) {
32958
+ lines.push("Cookies observed before a consent choice (metadata only; no cookie values):");
32959
+ for (const candidate of cookies) {
32960
+ const cookie = candidate && typeof candidate === "object" && !Array.isArray(candidate) ? candidate : {};
32961
+ lines.push(`- Cookie ${compactPreviewValue(cookie.name, "unnamed", 256)}; domain=${compactPreviewValue(cookie.domain, "unavailable", 253)}; party=${compactPreviewValue(cookie.party, "unknown", 40)}; category/purpose=${compactPreviewValue(cookie.purpose, "unknown", 80)}; essentiality=${compactPreviewValue(cookie.essentiality, "unknown", 40)}; observedAtMs=${previewObservedTiming(cookie.observedAtMs)}.`);
32962
+ }
32963
+ } else {
32964
+ lines.push("Cookies observed before a consent choice: none returned in this preliminary preview.");
32965
+ }
32966
+ if (trackers.length > 0) {
32967
+ lines.push("Tracking vendors/products observed before a consent choice:");
32968
+ for (const candidate of trackers) {
32969
+ const tracker = candidate && typeof candidate === "object" && !Array.isArray(candidate) ? candidate : {};
32970
+ const domains = Array.isArray(tracker.domains) ? tracker.domains.map((domain) => compactPreviewValue(domain, "unknown", 253)).join(", ") : "none returned";
32971
+ lines.push(`- Tracking vendor ${compactPreviewValue(tracker.vendor, "unknown", 160)}; product=${compactPreviewValue(tracker.product, "unavailable", 160)}; category/purpose=${compactPreviewValue(tracker.purpose, "unknown", 80)}; confidence=${compactPreviewValue(tracker.confidence, "unknown", 20)}; domains=${compactPreviewValue(domains, "none returned", 800)}.`);
32972
+ }
32973
+ lines.push("Tracker timing: per-tracker first-seen milliseconds are not part of the preliminary preview contract; do not infer them from cookie timing.");
32974
+ } else {
32975
+ lines.push("Tracking vendors/products observed before a consent choice: none returned in this partial preview.");
32976
+ }
32977
+ if (operationalVendors.length > 0) {
32978
+ lines.push("Operational, security, or consent-management vendors observed (separate from trackingVendorCount):");
32979
+ for (const candidate of operationalVendors) {
32980
+ const vendor = candidate && typeof candidate === "object" && !Array.isArray(candidate) ? candidate : {};
32981
+ const domains = Array.isArray(vendor.domains) ? vendor.domains.map((domain) => compactPreviewValue(domain, "unknown", 253)).join(", ") : "none returned";
32982
+ lines.push(`- Operational vendor ${compactPreviewValue(vendor.vendor, "unknown", 160)}; product=${compactPreviewValue(vendor.product, "unavailable", 160)}; category/purpose=${compactPreviewValue(vendor.purpose, "unknown", 80)}; confidence=${compactPreviewValue(vendor.confidence, "unknown", 20)}; domains=${compactPreviewValue(domains, "none returned", 800)}.`);
32983
+ }
32984
+ }
32985
+ if (String(capturedCookieCount) !== String(returnedCookieCount) || String(capturedTrackingVendorCount) !== String(returnedTrackingVendorCount) || String(capturedOperationalVendorCount) !== String(returnedOperationalVendorCount)) {
32986
+ lines.push(`Preview identity lists are bounded: ${capturedCookieCount} cookies captured/${returnedCookieCount} identities returned; ${capturedTrackingVendorCount} tracking vendors captured/${returnedTrackingVendorCount} identities returned; ${capturedOperationalVendorCount} operational vendors captured/${returnedOperationalVendorCount} identities returned. Use captured counts for checkpoint coverage and returned arrays for names.`);
32987
+ }
32988
+ const disclaimer = typeof preview.observationOnlyDisclaimer === "string" && preview.observationOnlyDisclaimer.trim() ? preview.observationOnlyDisclaimer.trim() : "Preliminary passive observations only; not findings, a score, or a final result.";
32989
+ lines.push(`${compactPreviewValue(disclaimer, "Preliminary passive observations only.", 500)} Continue sequential status polling until terminal status; at completed or completed_limited, retrieve certscore_get_scan_bundle before reporting the full scan results or final returned tally.`);
32990
+ return lines;
32991
+ }
32992
+ function boundedPreviewResultText(prefix, bodyLines, suffix) {
32993
+ const lines = [...prefix];
32994
+ let rendered = 0;
32995
+ for (const line of bodyLines) {
32996
+ if ([...lines, line, ...suffix].join("\n").length > MAX_TOOL_TEXT_CHARS) break;
32997
+ lines.push(line);
32998
+ rendered += 1;
32999
+ }
33000
+ if (rendered < bodyLines.length) {
33001
+ const omitted = `${bodyLines.length - rendered} additional preliminary preview line${bodyLines.length - rendered === 1 ? " was" : "s were"} omitted from TextContent to preserve the size limit; all bounded rows remain in structuredContent.`;
33002
+ if ([...lines, omitted, ...suffix].join("\n").length <= MAX_TOOL_TEXT_CHARS) lines.push(omitted);
33003
+ }
33004
+ lines.push(...suffix);
33005
+ return lines.join("\n");
32668
33006
  }
32669
33007
  function boundedResultText(header, bodyLines, value) {
32670
33008
  const footer = [OBSERVATION_ONLY_DISCLAIMER, INTERPRETATION_STATEMENT];
@@ -32761,6 +33099,24 @@ function scanBundleText(bundle) {
32761
33099
  if (coverage) {
32762
33100
  append(`Coverage: status=${coverage.status ?? "unknown"}; ${coverage.summary ?? "Review limitations before interpreting absence."}`);
32763
33101
  }
33102
+ const gpcResponse = bundle.gpcResponse && typeof bundle.gpcResponse === "object" && !Array.isArray(bundle.gpcResponse) ? bundle.gpcResponse : null;
33103
+ if (gpcResponse) {
33104
+ const proof = gpcResponse.comparison?.enabledProof;
33105
+ const californiaPolicy = gpcResponse.californiaPolicy;
33106
+ append(`GPC response: ${gpcResponse.findingTitle ?? "GPC response"}; status=${gpcResponse.status ?? "indeterminate"}; Sec-GPC: 1 proof retained on ${proof?.requestsWithSecGpc ?? 0} request(s).`);
33107
+ if (californiaPolicy?.applied === true && californiaPolicy.deductionPoints === 15) {
33108
+ append("California scoring policy: \u221215 points. This score effect is separate from the jurisdiction-neutral GPC comparison.");
33109
+ }
33110
+ }
33111
+ const postAccept = bundle.postAcceptObservation && typeof bundle.postAcceptObservation === "object" && !Array.isArray(bundle.postAcceptObservation) ? bundle.postAcceptObservation : null;
33112
+ if (postAccept && typeof postAccept.interpretation === "string") {
33113
+ const termination = postAccept.termination && typeof postAccept.termination === "object" && !Array.isArray(postAccept.termination) ? postAccept.termination : null;
33114
+ const intentionalEvidenceStop = termination?.kind === "evidence_satisfied" && termination.intentional === true ? " The observation then stopped intentionally because qualifying evidence had been captured." : "";
33115
+ append(`Accept Path: ${postAccept.interpretation}${intentionalEvidenceStop}`);
33116
+ for (const limitation of Array.isArray(postAccept.coverageLimitations) ? postAccept.coverageLimitations.slice(0, 3) : []) {
33117
+ append(`Accept Path coverage limitation: ${limitation}`);
33118
+ }
33119
+ }
32764
33120
  const postRefusal = bundle.postRefusalObservation && typeof bundle.postRefusalObservation === "object" && !Array.isArray(bundle.postRefusalObservation) ? bundle.postRefusalObservation : null;
32765
33121
  if (postRefusal && typeof postRefusal.interpretation === "string") {
32766
33122
  const termination = postRefusal.termination && typeof postRefusal.termination === "object" && !Array.isArray(postRefusal.termination) ? postRefusal.termination : null;
@@ -32928,6 +33284,8 @@ function buildScanBundle(input) {
32928
33284
  scoreVersion: input.scan.scoreVersion ?? null,
32929
33285
  scoreUpdatedAt: input.scan.scoreUpdatedAt ?? null,
32930
33286
  riskLevel: input.scan.riskLevel ?? null,
33287
+ ...input.scan.gpcResponse ? { gpcResponse: input.scan.gpcResponse } : {},
33288
+ postAcceptObservation: input.scan.postAcceptObservation ?? null,
32931
33289
  postRefusalObservation: input.scan.postRefusalObservation ?? null,
32932
33290
  provenance: scanProvenance(input.scan, "existing_scan_retrieved"),
32933
33291
  interpretationGuidance: interpretationGuidance(SCAN_BUNDLE_INTERPRETATION_STATEMENT),
@@ -33161,6 +33519,8 @@ function buildScanBundle(input) {
33161
33519
  scoreVersion: bundle.scoreVersion,
33162
33520
  scoreUpdatedAt: bundle.scoreUpdatedAt,
33163
33521
  riskLevel: bundle.riskLevel,
33522
+ ...bundle.gpcResponse ? { gpcResponse: bundle.gpcResponse } : {},
33523
+ postAcceptObservation: bundle.postAcceptObservation,
33164
33524
  postRefusalObservation: bundle.postRefusalObservation,
33165
33525
  provenance: bundle.provenance,
33166
33526
  interpretationGuidance: bundle.interpretationGuidance,
@@ -33275,23 +33635,11 @@ function explainFinding(report, findingId) {
33275
33635
  }
33276
33636
 
33277
33637
  // src/server.ts
33278
- var DEFAULT_MCP_SCAN_TOOL_BUDGET_MS = 25e3;
33279
- var MAX_MCP_SCAN_TOOL_BUDGET_MS = 45e3;
33280
- var MCP_SCAN_TOOL_RESPONSE_RESERVE_MS = 1e3;
33281
33638
  var LIGHT_MCP_BUNDLE_RESPONSE_CEILING_BYTES = 25e3;
33282
- function resolveMcpScanSiteWaitBudget(input) {
33283
- const totalBudgetMs = Math.min(
33284
- input.maxWaitSeconds ? input.maxWaitSeconds * 1e3 : DEFAULT_MCP_SCAN_TOOL_BUDGET_MS,
33285
- MAX_MCP_SCAN_TOOL_BUDGET_MS
33286
- );
33287
- const elapsedMs = Math.max(0, input.nowMs - input.startedAtMs);
33288
- return {
33289
- elapsedMs,
33290
- remainingWaitMs: Math.max(0, totalBudgetMs - elapsedMs - MCP_SCAN_TOOL_RESPONSE_RESERVE_MS),
33291
- responseReserveMs: MCP_SCAN_TOOL_RESPONSE_RESERVE_MS,
33292
- totalBudgetMs
33293
- };
33294
- }
33639
+ var MCP_SCAN_SITE_TARGET_RESPONSE_MS = 11e3;
33640
+ var MCP_SCAN_SITE_TARGET_RESPONSE_RESERVE_MS = 250;
33641
+ var MCP_SCAN_SITE_PREVIEW_POLL_INTERVAL_MS = 750;
33642
+ var MCP_SCAN_SITE_MAX_PREVIEW_WAIT_MS = 1e4;
33295
33643
  function exampleDomainDemoSubstitution(requestedUrl, demoUrl) {
33296
33644
  if (!demoUrl) return null;
33297
33645
  try {
@@ -33315,10 +33663,7 @@ function withExampleDomainDemo(value, substitution) {
33315
33663
  return substitution ? { ...value, demoSubstitution: substitution } : value;
33316
33664
  }
33317
33665
  function exampleDomainDemoText(value, substitution) {
33318
- if (!substitution) return void 0;
33319
- const status = typeof value.status === "string" ? ` Status=${value.status}.` : "";
33320
- const scanId = typeof value.scanId === "string" ? ` ScanId=${value.scanId}.` : "";
33321
- return `${substitution.message}${status}${scanId} Full result and substitution provenance are in structuredContent.`;
33666
+ return scanSiteText(value, substitution ? [`${substitution.message} Substitution provenance is in structuredContent.`] : []);
33322
33667
  }
33323
33668
  async function retryTransientOriginFailure(operation) {
33324
33669
  try {
@@ -33345,6 +33690,15 @@ function scanCreationMetadata(value) {
33345
33690
  upgradeMessage: value.upgradeMessage
33346
33691
  };
33347
33692
  }
33693
+ function activeScan(value) {
33694
+ return value.status === "queued" || value.status === "running" || value.status === "finalizing";
33695
+ }
33696
+ function hasPreConsentPreview(value) {
33697
+ return Boolean(value.preConsentPreview && typeof value.preConsentPreview === "object" && !Array.isArray(value.preConsentPreview));
33698
+ }
33699
+ function delay(ms) {
33700
+ return new Promise((resolve) => setTimeout(resolve, ms));
33701
+ }
33348
33702
  function toolContract(name) {
33349
33703
  const contract = certScoreMcpToolContracts.find((candidate) => candidate.name === name);
33350
33704
  if (!contract) {
@@ -33531,6 +33885,7 @@ function createCertScoreMcpServer(options = {}) {
33531
33885
  toolContract("certscore_scan_site"),
33532
33886
  async (input, extra) => {
33533
33887
  const toolStartedAtMs = Date.now();
33888
+ const creationStartedAtMs = toolStartedAtMs;
33534
33889
  const client2 = clientForRequest(extra);
33535
33890
  const demoSubstitution = exampleDomainDemoSubstitution(input.url, options.exampleDomainDemoUrl);
33536
33891
  const effectiveUrl = demoSubstitution?.effectiveUrl ?? input.url;
@@ -33539,56 +33894,78 @@ function createCertScoreMcpServer(options = {}) {
33539
33894
  freshness: input.freshness ?? "latest",
33540
33895
  scanFrom: input.scanFrom
33541
33896
  });
33542
- if (input.waitForCompletion === false || created.type === "certscore_scan") {
33543
- const guided = withExampleDomainDemo(withMcpAgentGuidance(created), demoSubstitution);
33544
- return toToolResult(guided, exampleDomainDemoText(guided, demoSubstitution));
33545
- }
33546
- const waitBudget = resolveMcpScanSiteWaitBudget({
33547
- maxWaitSeconds: input.maxWaitSeconds,
33548
- nowMs: Date.now(),
33549
- startedAtMs: toolStartedAtMs
33550
- });
33551
- if (waitBudget.remainingWaitMs === 0) {
33552
- console.warn(JSON.stringify({
33553
- event: "mcp.certscore_scan_site.wait_budget_consumed",
33554
- jobId: created.jobId ?? null,
33555
- scanId: created.scanId ?? created.scan_id ?? null,
33556
- status: created.status ?? null,
33557
- ...waitBudget
33558
- }));
33559
- const guided = withExampleDomainDemo(withMcpAgentGuidance(created), demoSubstitution);
33560
- return toToolResult(guided, exampleDomainDemoText(guided, demoSubstitution));
33561
- }
33562
- const waitAbortController = new AbortController();
33563
- const waitAbortTimer = setTimeout(() => waitAbortController.abort(), waitBudget.remainingWaitMs);
33564
- try {
33565
- const internalMcpOperation = { operation: "scan_site_wait", scanId: created.scanId ?? created.scan_id ?? created.jobId };
33566
- const completed = await client2.scans.wait(created, {
33567
- maxWaitMs: waitBudget.remainingWaitMs,
33568
- internalMcpOperation,
33569
- signal: waitAbortController.signal
33570
- });
33571
- const guided = withExampleDomainDemo(withMcpAgentGuidance({
33572
- ...completed,
33573
- ...scanCreationMetadata(created)
33574
- }), demoSubstitution);
33575
- return toToolResult(guided, exampleDomainDemoText(guided, demoSubstitution));
33576
- } catch (error2) {
33577
- const scanId = created.scanId ?? created.scan_id;
33578
- console.warn(JSON.stringify({
33579
- event: "mcp.certscore_scan_site.wait_deferred",
33580
- errorName: error2 instanceof Error ? error2.name : "UnknownError",
33581
- jobId: created.jobId ?? null,
33582
- scanId: scanId ?? null,
33583
- status: created.status ?? null,
33584
- ...waitBudget
33897
+ console.log(JSON.stringify({
33898
+ event: "mcp.certscore_scan_site.creation_completed",
33899
+ durationMs: Date.now() - creationStartedAtMs,
33900
+ executionMode: created.executionMode ?? null,
33901
+ hasScanId: Boolean(created.scanId ?? created.scan_id),
33902
+ reused: created.reused === true,
33903
+ status: created.status ?? null
33904
+ }));
33905
+ let initialResult = created;
33906
+ const stableScanId = typeof created.scanId === "string" && created.scanId ? created.scanId : typeof created.scan_id === "string" && created.scan_id ? created.scan_id : typeof created.jobId === "string" && created.jobId ? created.jobId : null;
33907
+ const configuredPreviewWaitMs = options.toolProfile === "light" ? Math.min(
33908
+ Math.max(0, options.initialPreConsentPreviewWaitMs ?? 1e4),
33909
+ MCP_SCAN_SITE_MAX_PREVIEW_WAIT_MS
33910
+ ) : 0;
33911
+ const totalRemainingMs = Math.max(
33912
+ 0,
33913
+ toolStartedAtMs + MCP_SCAN_SITE_TARGET_RESPONSE_MS - MCP_SCAN_SITE_TARGET_RESPONSE_RESERVE_MS - Date.now()
33914
+ );
33915
+ const previewWaitMs = Math.min(configuredPreviewWaitMs, totalRemainingMs);
33916
+ if (stableScanId && previewWaitMs > 0 && activeScan(initialResult)) {
33917
+ const previewWaitStartedAtMs = Date.now();
33918
+ const previewDeadlineMs = previewWaitStartedAtMs + previewWaitMs;
33919
+ let internalReadCount = 0;
33920
+ try {
33921
+ while (Date.now() < previewDeadlineMs && activeScan(initialResult) && !hasPreConsentPreview(initialResult)) {
33922
+ await delay(Math.min(MCP_SCAN_SITE_PREVIEW_POLL_INTERVAL_MS, previewDeadlineMs - Date.now()));
33923
+ const requestRemainingMs = previewDeadlineMs - Date.now();
33924
+ if (requestRemainingMs <= 0) break;
33925
+ const waitAbortController = new AbortController();
33926
+ const waitAbortTimer = setTimeout(() => waitAbortController.abort(), requestRemainingMs);
33927
+ try {
33928
+ internalReadCount += 1;
33929
+ const status = await client2.scans.status(stableScanId, {
33930
+ internalMcpOperation: { operation: "scan_site_wait", scanId: stableScanId },
33931
+ signal: waitAbortController.signal
33932
+ });
33933
+ initialResult = {
33934
+ ...status,
33935
+ ...scanCreationMetadata(created)
33936
+ };
33937
+ } finally {
33938
+ clearTimeout(waitAbortTimer);
33939
+ }
33940
+ }
33941
+ } catch (error2) {
33942
+ console.warn(JSON.stringify({
33943
+ event: "mcp.certscore_scan_site.preview_wait_deferred",
33944
+ durationMs: Date.now() - previewWaitStartedAtMs,
33945
+ errorName: error2 instanceof Error ? error2.name : "UnknownError",
33946
+ hasPreview: hasPreConsentPreview(initialResult),
33947
+ internalReadCount,
33948
+ scanId: stableScanId
33949
+ }));
33950
+ }
33951
+ console.log(JSON.stringify({
33952
+ event: "mcp.certscore_scan_site.preview_wait_completed",
33953
+ durationMs: Date.now() - previewWaitStartedAtMs,
33954
+ hasPreview: hasPreConsentPreview(initialResult),
33955
+ internalReadCount,
33956
+ scanId: stableScanId,
33957
+ status: initialResult.status ?? null,
33958
+ totalDurationMs: Date.now() - toolStartedAtMs
33585
33959
  }));
33586
- const guided = withExampleDomainDemo(withMcpAgentGuidance(created), demoSubstitution);
33587
- return toToolResult(guided, exampleDomainDemoText(guided, demoSubstitution));
33588
- } finally {
33589
- clearTimeout(waitAbortTimer);
33590
33960
  }
33961
+ const guided = withExampleDomainDemo(withMcpAgentGuidance(initialResult, "unknown", "scan_creation"), demoSubstitution);
33962
+ return toToolResult(guided, exampleDomainDemoText(guided, demoSubstitution));
33591
33963
  } catch (error2) {
33964
+ console.warn(JSON.stringify({
33965
+ event: "mcp.certscore_scan_site.creation_failed",
33966
+ durationMs: Date.now() - creationStartedAtMs,
33967
+ errorName: error2 instanceof Error ? error2.name : "UnknownError"
33968
+ }));
33592
33969
  return toToolError(error2);
33593
33970
  }
33594
33971
  }