@certscore/mcp 0.2.22 → 0.2.23

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 CHANGED
@@ -10,7 +10,7 @@ CertScore.ai MCP Light is live in the [GitHub MCP Registry](https://github.com/m
10
10
  | Transport | Streamable HTTP |
11
11
  | Authentication | None |
12
12
  | Tools | `certscore_scan_site` → `certscore_get_scan_status` → `certscore_get_scan_bundle` |
13
- | Current hosted version | `0.2.22` |
13
+ | Current hosted version | `0.2.23` |
14
14
 
15
15
  [Start with MCP Light](https://certscore.ai/mcp/light?utm_source=github&utm_medium=mcp_registry&utm_campaign=github_mcp_registry_launch) · [Install in Cursor](https://cursor.com/link/mcp/install?name=CertScore.ai&config=eyJ1cmwiOiJodHRwczovL21jcC5jZXJ0c2NvcmUuYWkvbWNwL2xpZ2h0In0%3D) · [Read the installation reference](../../docs/mcp-light-install.md)
16
16
 
@@ -57,7 +57,7 @@ Canonical Light workflow:
57
57
  5. Poll `certscore_get_scan_status` using `scanId` only. Never poll until `scanId` exists.
58
58
  6. Stop polling at any terminal status. At `completed` or `completed_limited`, call `certscore_get_scan_bundle` before reporting full scan results, and use its final returned tally, canonical findings, and limitations; for other terminal states, follow the returned error guidance.
59
59
  7. Use `detail=findings` for a compact finding review.
60
- 8. Use `detail=evidence` for evidence digests and references.
60
+ 8. Use `detail=evidence` for finding digests, bounded external-request examples, policy-surface candidates, and references, including when no finding was projected. A request for an external script does not by itself establish tracking; use `certscore_get_report_evidence_page` for deeper retained report evidence.
61
61
  9. If truncated, follow `recommendedNextAction` or increase `maxBytes`.
62
62
  10. Summarize findings together with coverage limitations and the report URL.
63
63
 
@@ -98,7 +98,10 @@ The sections below document the broader authenticated and local package surfaces
98
98
  - `certscore_get_scan_status` - 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.
99
99
  - `certscore_get_report` - 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.
100
100
  - `certscore_get_evidence` - 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.
101
- - `certscore_get_scan_bundle` - 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 results distinguish registered decisions from retained after-click facts. Their execution reports succeeded for a completed click and bounded observation, and succeeded_with_confirmation when the consent decision is also verified. Count both execution success statuses; registered successful paths may omit afterAction, and missing historical execution means unavailable. Optional afterAction summaries remain useful when registration is unconfirmed; absent or failed capture remains explicitly limited. Consume canonical findings for any scoring effect. Results are automated public-web observations, not legal advice, certification, or a compliance determination.
101
+ - `certscore_get_scan_bundle` - 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 results distinguish registered decisions from retained after-click facts. Their execution reports succeeded for a completed click and bounded observation, and succeeded_with_confirmation when the consent decision is also verified. Optional afterAction summaries remain useful when registration is unconfirmed; absent or failed capture remains explicitly limited. Consume canonical findings for any scoring effect. Results are automated public-web observations, not legal advice, certification, or a compliance determination.
102
+
103
+ Count both execution success statuses; registered successful paths may omit afterAction, and missing historical execution means unavailable.
104
+
102
105
 
103
106
  Post-refusal observation may intentionally stop after the first qualifying non-essential activity or retained consent-signal contradiction. A confirmed observation with `termination.kind=evidence_satisfied` is positive evidence for the returned observation, not an inconclusive Reject Path result. `coverageLimitations` describe only additional behavior or persistence that was not measured.
104
107
  - `certscore_export_findings` - Return structured findings plus completed-limited no-go disposition and guidance for downstream review or ticketing workflows.
@@ -25091,7 +25091,7 @@ var certScoreMcpToolContracts = [
25091
25091
  {
25092
25092
  name: "certscore_get_scan_bundle",
25093
25093
  title: "Get scan bundle",
25094
- 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 results distinguish registered decisions from retained after-click facts. Their execution reports succeeded for a completed click and bounded observation, and succeeded_with_confirmation when the consent decision is also verified. Optional afterAction summaries remain useful when registration is unconfirmed; absent or failed capture remains explicitly limited. Consume canonical findings for any scoring effect. Results are automated public-web observations, not legal advice, certification, or a compliance determination.",
25094
+ description: "Returns the completed or completed-limited CertScore evidence bundle for a stable scanId as concise TextContent and matching structuredContent. The default summary distinguishes observed external domains from classified tracker vendors and states the public-page scope. Use detail=evidence to inspect bounded retained request examples and policy-surface candidates even when there are no findings; use certscore_get_report_evidence_page for deeper report evidence. Available sections also include canonical findings, pre-consent cookie and tracker evidence, coverage limitations, persisted execution provenance, and retrieval URLs. Detail tiers and byte budgets report returned, total, truncated, and omitted-section metadata. Accept and Reject results distinguish registered decisions from retained after-click facts. Their execution reports succeeded for a completed click and bounded observation, and succeeded_with_confirmation when the consent decision is also verified. Optional afterAction summaries remain useful when registration is unconfirmed; absent or failed capture remains explicitly limited. Consume canonical findings for any scoring effect. Results are automated public-web observations, not legal advice, certification, or a compliance determination.",
25095
25095
  inputSchema: mcpGetScanBundleInputSchema,
25096
25096
  outputSchema: mcpScanBundleOutputSchema,
25097
25097
  annotations: { title: "Get scan bundle", ...accountedInternalReadAnnotations }
@@ -37660,6 +37660,11 @@ function compactPriorityEvidenceSummary(summary) {
37660
37660
  };
37661
37661
  }
37662
37662
  function bundleEvidenceSummary(evidence, findings, links, includeDiagnostics) {
37663
+ const inventory = evidence.unclassifiedExternalRequests;
37664
+ const requestRows = Array.isArray(inventory) ? inventory : inventory && typeof inventory === "object" && Array.isArray(inventory.items) ? inventory.items : [];
37665
+ const externalRequests = requestRows.filter((value) => Boolean(value) && typeof value === "object" && !Array.isArray(value) && typeof value.hostname === "string");
37666
+ const policyInventory = evidence.policySurfaceCoverage;
37667
+ const policyRows = policyInventory && typeof policyInventory === "object" && Array.isArray(policyInventory.items) ? policyInventory.items : [];
37663
37668
  const digests = findings.slice(0, 3).map((finding) => {
37664
37669
  const findingEvidence = finding.evidence && typeof finding.evidence === "object" && !Array.isArray(finding.evidence) ? finding.evidence : {};
37665
37670
  return {
@@ -37672,7 +37677,19 @@ function bundleEvidenceSummary(evidence, findings, links, includeDiagnostics) {
37672
37677
  });
37673
37678
  return {
37674
37679
  digests,
37675
- evidenceAvailable: digests.length > 0 || Object.keys(evidence).length > 0,
37680
+ evidenceAvailable: digests.length > 0 || externalRequests.length > 0 || policyRows.length > 0 || Object.keys(evidence).length > 0,
37681
+ ...externalRequests.length ? { externalRequestSample: externalRequests.slice(0, 3).map((row) => ({
37682
+ host: row.hostname ?? null,
37683
+ path: row.path ?? null,
37684
+ resourceType: row.resourceType ?? null,
37685
+ observedAtMs: row.observedAtMs ?? null,
37686
+ interpretation: "External request observed; purpose and data transmission not established by this row."
37687
+ })), externalRequestSampleTotal: externalRequests.length } : {},
37688
+ ...policyRows.length ? { policySurfaceCandidates: policyRows.slice(0, 3).flatMap((value) => {
37689
+ if (!value || typeof value !== "object" || Array.isArray(value)) return [];
37690
+ const row = value;
37691
+ return typeof row.url === "string" ? [{ type: row.type ?? null, url: row.url }] : [];
37692
+ }), policyEvidenceNextStep: "For a policy passage, use certscore_get_report_evidence_page with this scanId and inspect the report's retained policy evidence." } : {},
37676
37693
  evidenceSafetyNotes: Array.isArray(evidence.evidenceSafetyNotes) ? evidence.evidenceSafetyNotes.slice(0, 3).map((note) => boundedText(note, 300)) : [],
37677
37694
  references: Object.fromEntries(Object.entries(links).filter(([key, value]) => ["findings", "pulse", "report", "preConsentCookiesTrackers"].includes(key) && typeof value === "string")),
37678
37695
  ...includeDiagnostics ? {
@@ -38299,7 +38316,18 @@ function scanBundleText(bundle, options = {}) {
38299
38316
  };
38300
38317
  const coverage = bundle.coverage && typeof bundle.coverage === "object" && !Array.isArray(bundle.coverage) ? bundle.coverage : null;
38301
38318
  if (coverage) {
38302
- append(`Coverage: status=${coverage.status ?? "unknown"}; ${coverage.summary ?? "Review limitations before interpreting absence."}`);
38319
+ append(`Coverage: ${coverage.scopeSummary ?? coverage.summary ?? "Review limitations before interpreting absence."}`);
38320
+ }
38321
+ const counts = bundle.summary?.counts;
38322
+ if (counts && typeof counts === "object" && Number.isInteger(counts.thirdPartyDomainsObserved) && Number.isInteger(counts.classifiedTrackerVendors)) {
38323
+ append(`Observed external domains: ${counts.thirdPartyDomainsObserved}; classified tracker vendors: ${counts.classifiedTrackerVendors}. External contact alone does not establish tracking.`);
38324
+ }
38325
+ if (bundle.detail === "evidence" || bundle.detail === "full") {
38326
+ const sample = bundle.evidenceSummary?.externalRequestSample;
38327
+ if (Array.isArray(sample) && sample.length > 0) {
38328
+ const first = sample[0];
38329
+ append(`Retained external request: ${first.host ?? "unknown host"}${first.path ?? ""}${first.resourceType ? ` (${first.resourceType})` : ""}. Purpose was not established by this request.`);
38330
+ }
38303
38331
  }
38304
38332
  const gpcResponse = bundle.gpcResponse && typeof bundle.gpcResponse === "object" && !Array.isArray(bundle.gpcResponse) ? bundle.gpcResponse : null;
38305
38333
  if (gpcResponse) {
@@ -38338,8 +38366,8 @@ function scanBundleText(bundle, options = {}) {
38338
38366
  if (overview) append(overview);
38339
38367
  const transportSecurity = bundle.transportSecurity && typeof bundle.transportSecurity === "object" && !Array.isArray(bundle.transportSecurity) ? bundle.transportSecurity : null;
38340
38368
  if (transportSecurity) {
38341
- const counts = transportSecurity.observationCounts && typeof transportSecurity.observationCounts === "object" ? transportSecurity.observationCounts : {};
38342
- append(`Transport security: status=${transportSecurity.status ?? "unavailable"}; retained evidence=${transportSecurity.evidenceRetained === true ? "yes" : "no"}; canonical observations=${counts.total ?? 0}; concerns/review=${counts.concernOrReview ?? 0}; unavailable=${counts.unavailable ?? 0}.`);
38369
+ const counts2 = transportSecurity.observationCounts && typeof transportSecurity.observationCounts === "object" ? transportSecurity.observationCounts : {};
38370
+ append(`Transport security: status=${transportSecurity.status ?? "unavailable"}; retained evidence=${transportSecurity.evidenceRetained === true ? "yes" : "no"}; canonical observations=${counts2.total ?? 0}; concerns/review=${counts2.concernOrReview ?? 0}; unavailable=${counts2.unavailable ?? 0}.`);
38343
38371
  for (const observation of Array.isArray(transportSecurity.observations) ? transportSecurity.observations : []) {
38344
38372
  append(`Transport observation: ${observation.label ?? observation.id ?? "unknown"}; status=${observation.status ?? "unknown"}; ${observation.summary ?? "Review the structured transport evidence."}`);
38345
38373
  }
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
package/dist/tools.js CHANGED
@@ -609,6 +609,17 @@ function compactPriorityEvidenceSummary(summary) {
609
609
  };
610
610
  }
611
611
  function bundleEvidenceSummary(evidence, findings, links, includeDiagnostics) {
612
+ const inventory = evidence.unclassifiedExternalRequests;
613
+ const requestRows = Array.isArray(inventory)
614
+ ? inventory
615
+ : inventory && typeof inventory === "object" && Array.isArray(inventory.items)
616
+ ? inventory.items
617
+ : [];
618
+ const externalRequests = requestRows.filter((value) => Boolean(value) && typeof value === "object" && !Array.isArray(value) && typeof value.hostname === "string");
619
+ const policyInventory = evidence.policySurfaceCoverage;
620
+ const policyRows = policyInventory && typeof policyInventory === "object" && Array.isArray(policyInventory.items)
621
+ ? policyInventory.items
622
+ : [];
612
623
  const digests = findings.slice(0, 3).map((finding) => {
613
624
  const findingEvidence = finding.evidence && typeof finding.evidence === "object" && !Array.isArray(finding.evidence)
614
625
  ? finding.evidence
@@ -629,7 +640,20 @@ function bundleEvidenceSummary(evidence, findings, links, includeDiagnostics) {
629
640
  });
630
641
  return {
631
642
  digests,
632
- evidenceAvailable: digests.length > 0 || Object.keys(evidence).length > 0,
643
+ evidenceAvailable: digests.length > 0 || externalRequests.length > 0 || policyRows.length > 0 || Object.keys(evidence).length > 0,
644
+ ...(externalRequests.length ? { externalRequestSample: externalRequests.slice(0, 3).map(row => ({
645
+ host: row.hostname ?? null,
646
+ path: row.path ?? null,
647
+ resourceType: row.resourceType ?? null,
648
+ observedAtMs: row.observedAtMs ?? null,
649
+ interpretation: "External request observed; purpose and data transmission not established by this row."
650
+ })), externalRequestSampleTotal: externalRequests.length } : {}),
651
+ ...(policyRows.length ? { policySurfaceCandidates: policyRows.slice(0, 3).flatMap(value => {
652
+ if (!value || typeof value !== "object" || Array.isArray(value))
653
+ return [];
654
+ const row = value;
655
+ return typeof row.url === "string" ? [{ type: row.type ?? null, url: row.url }] : [];
656
+ }), policyEvidenceNextStep: "For a policy passage, use certscore_get_report_evidence_page with this scanId and inspect the report's retained policy evidence." } : {}),
633
657
  evidenceSafetyNotes: Array.isArray(evidence.evidenceSafetyNotes)
634
658
  ? evidence.evidenceSafetyNotes.slice(0, 3).map((note) => boundedText(note, 300))
635
659
  : [],
@@ -1361,7 +1385,18 @@ export function scanBundleText(bundle, options = {}) {
1361
1385
  ? bundle.coverage
1362
1386
  : null;
1363
1387
  if (coverage) {
1364
- append(`Coverage: status=${coverage.status ?? "unknown"}; ${coverage.summary ?? "Review limitations before interpreting absence."}`);
1388
+ append(`Coverage: ${coverage.scopeSummary ?? coverage.summary ?? "Review limitations before interpreting absence."}`);
1389
+ }
1390
+ const counts = bundle.summary?.counts;
1391
+ if (counts && typeof counts === "object" && Number.isInteger(counts.thirdPartyDomainsObserved) && Number.isInteger(counts.classifiedTrackerVendors)) {
1392
+ append(`Observed external domains: ${counts.thirdPartyDomainsObserved}; classified tracker vendors: ${counts.classifiedTrackerVendors}. External contact alone does not establish tracking.`);
1393
+ }
1394
+ if (bundle.detail === "evidence" || bundle.detail === "full") {
1395
+ const sample = bundle.evidenceSummary?.externalRequestSample;
1396
+ if (Array.isArray(sample) && sample.length > 0) {
1397
+ const first = sample[0];
1398
+ append(`Retained external request: ${first.host ?? "unknown host"}${first.path ?? ""}${first.resourceType ? ` (${first.resourceType})` : ""}. Purpose was not established by this request.`);
1399
+ }
1365
1400
  }
1366
1401
  const gpcResponse = bundle.gpcResponse && typeof bundle.gpcResponse === "object" && !Array.isArray(bundle.gpcResponse)
1367
1402
  ? bundle.gpcResponse
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@certscore/mcp",
3
- "version": "0.2.22",
3
+ "version": "0.2.23",
4
4
  "mcpName": "ai.certscore/mcp",
5
5
  "private": false,
6
6
  "description": "MCP server for CertScore public website risk-signal workflows.",
package/server-light.json CHANGED
@@ -24,7 +24,7 @@
24
24
  "theme": "dark"
25
25
  }
26
26
  ],
27
- "version": "0.2.22",
27
+ "version": "0.2.23",
28
28
  "remotes": [
29
29
  {
30
30
  "type": "streamable-http",
package/server.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "url": "https://github.com/ergoveritas1-alt/certscore.ai",
9
9
  "source": "github"
10
10
  },
11
- "version": "0.2.22",
11
+ "version": "0.2.23",
12
12
  "remotes": [
13
13
  {
14
14
  "type": "streamable-http",
@@ -20,7 +20,7 @@
20
20
  "registryType": "npm",
21
21
  "registryBaseUrl": "https://registry.npmjs.org",
22
22
  "identifier": "@certscore/mcp",
23
- "version": "0.2.22",
23
+ "version": "0.2.23",
24
24
  "transport": {
25
25
  "type": "stdio"
26
26
  },