{"id":"4172ab8c-ff37-4ac0-ba7d-d6739e72033c","slug":"scovant-core","kind":"mcp","name":"scovant-core","summary":"Open-source, evidence-first scanner for passive AI agent readiness signals on websites.","owner":"Scovant","repoUrl":"https://github.com/Scovant/scovant-core","license":"Apache-2.0","licenseTier":"permissive","trust":"community","stars":0,"match":null,"fewStars":true,"format":"mcp","createdAt":"2026-09-04T11:52:57.000Z","addedAt":"2026-11-05T21:20:45.090Z","logoUrl":"https://avatars.githubusercontent.com/u/270341275?v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["developer-tools","data-analytics","memory-knowledge"],"tags":["agent-readiness","agentready","ai-agents","cli","llms-txt","python","robots-txt","structured-data"],"runtime":"python","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-11-06T06:12:10.054Z","sample":false,"url":"https://conduits.dev/tools/scovant-core","language":"Python","transports":["stdio"],"install":{"pypi":"scovant-core"},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"# Scovant Core\n\n<!-- mcp-name: io.github.Scovant/scovant-core -->\n\n## Definition\n\nScovant Core is an open-source, evidence-first scanner for passive AI-agent readiness signals on websites.\n\nScovant Core measures what a site declares. Scovant Cloud measures what real agents actually experience.\n\nCore does NOT execute real agents.\n\nIt reads what the site already exposes on request: robots/crawler policy,\nstructured data, llms.txt, machine-readable discovery, MCP metadata, WebMCP\ndeclaration, commerce metadata, HTTP semantics, and its own usage in CI.\n\n> A high Technical Readiness rating does not prove that autonomous agents can complete real workflows on the site.\n\n## 30-second install\n\n```bash\nuvx --from scovant-core scovant scan https://example.com   # no install, needs uv\npipx run --spec scovant-core scovant scan https://example.com\npip install scovant-core                                    # Python >= 3.12\npip install \"scovant-core[tokens]\"                          # + bundled tokenizer for PAGE_TOKEN_BLOAT\nnpx @scovant/core scan https://example.com                  # Node launcher, needs uv/pipx/python3\n```\n\n### Reproducible install\n\nSame Core version does not guarantee the same dependency graph months\nlater. Each release ships exact pins:\n\n    pip install \"scovant-core==0.24.1\" -c https://raw.githubusercontent.com/Scovant/scovant-core/v0.24.1/constraints/constraints-0.24.1.txt\n\nEvery report records what actually ran (`provenance.dependencies`,\n`provenance.environment_digest`).\n\n## Example output\n\nRunning `scovant scan https://example.com` against a\nwell-instrumented commerce site produces text output shaped like this (real\noutput, rendered — never from a live scan — from the `commerce-good` test\nfixture; the established readiness checks have nothing to report, so \"Top\nfindings\" carries only the site's three `[security]`-tagged findings — the\nSECURITY checks are never rated, but a FAIL/WARN among them still surfaces\nin \"Top findings\", tagged `[security]`, appended after any readiness\nFAIL/WARN). \"Diagnostics\" tallies the readiness checks' own verdicts; they\nare diagnostics and carry no weight in Technical Readiness. The\n\"Experimental (not scored)\" block lists every\nexperimental check that evaluated to something other than `N/A` on this\nscan (including a WARN, as below — experimental findings are still shown,\njust never scored), plus a compact \"N/A: ...\" line naming the experimental\nchecks that had nothing to evaluate — so every check the header counts is\nnamed somewhere, never merely counted. No check affects Technical\nReadiness; pass `--experimental` to also run the experimental checks gated\nbehind that flag (omit it and they're skipped entirely, not evaluated as\nN/A) and rank experimental findings with the rest — the scan's scope is then\n`CUSTOM`. The \"Agentic Security & Trust\" block below it is the 18 SECURITY\nchecks' own summary — see `docs/security.md` for the full boundary of what\nit does and does not test.\n\n```text\nSCOVANT CORE\n──────────────────────────────────────────────\n\nTarget: https://example.com/\nProfile: commerce (auto → commerce, confidence 0.85)\nCore version: 0.24.1\n\nTechnical Readiness  82 / 100  B · coverage 97% · model R2.1@7389c208c89e\nNot measured by Core: MCP_DISCOVERY_INVALID (handshake_not_performed)\nDiagnostics (51 readiness checks): 40 pass · 1 warn · 0 fail\n\nCapabilities detected (descriptive, not scored)\n  mcp: present\n  webmcp: absent\n  ucp: present\n  llms_txt: present\n  openapi: not_checked\n  oauth: not_checked\n  content_signal: present\n  security_txt: present\n\nAgentReady v1.0 (descriptive, not scored): MUST 3/3 measured — 3 pass · SHOULD 5/12 measured — 5 pass · MAY none measured (0/3)\n  Mapping: docs/standards/agentready.md\n\n69 checks\n51 PASS\n3 WARN\n1 FAIL\n14 N/A\n0 ERROR\n\nTop findings\n\nFAIL  [security] CORE-SECURITY-003\n      Neither Content-Security-Policy nor X-Frame-Options is sent.\n\nWARN  [security] CORE-SECURITY-002\n      No Strict-Transport-Security header.\n\nWARN  [security] CORE-SECURITY-005\n      Missing: referrer-policy, x-content-type-options.\n\nExperimental (not scored)\n──────────────────────────────────────────────\nPASS  CORE-ACCESS-011\n      llms.txt links useful same-origin pages and carries no misplaced policy or template text.\n\nPASS  CORE-INTERFACE-008\n      A UCP profile is published and valid.\n\nPASS  CORE-MACHINE-012\n      The structured price matches a visible price on the page.\n\nWARN  CORE-OPERABILITY-011\n      3 of 3 machine surface(s) are not linked from anything an agent reads: llms_txt, mcp, ucp.\n\nPASS  [security] CORE-SECURITY-009\n      No administrative/destructive interfaces advertised.\n\nPASS  [security] CORE-SECURITY-011\n      No indicators found.\n\nPASS  [security] CORE-SECURITY-012\n      No indicators found.\n\nPASS  [security] CORE-SECURITY-013\n      No indicators found.\n\nPASS  [security] CORE-SECURITY-014\n      No indicators found.\n\nPASS  [security] CORE-SECURITY-015\n      No indicators found.\n\nPASS  [security] CORE-SECURITY-016\n      No indicators found.\n\nN/A: CORE-INTERFACE-004, CORE-INTERFACE-009, CORE-MACHINE-013, CORE-OPERABILITY-007, CORE-SECURITY-010, CORE-SECURITY-017, CORE-SECURITY-018\n\nAGENTIC SECURITY & TRUST  PASSIVE SIGNALS ONLY\n──────────────────────────────────────────────\nCritical                  0\nHigh                      0\nMedium                    1\nLow                       2\nauth                      PASS 0  WARN 0  FAIL 0\nData exposure             PASS 3  WARN 0  FAIL 0\nDisclosure                PASS 1  WARN 0  FAIL 0\nPrompt surface            PASS 6  WARN 0  FAIL 0\nWeb baseline              PASS 1  WARN 2  FAIL 1\nObserved authorization    NOT TESTED\nVerified agent identity   NOT TESTED\nPrompt-injection resilience NOT TESTED\nTool invocation safety    NOT TESTED\nThis section evaluates tested AI-agent security controls and machine-facing security signals. It is not an overall website or application security rating.\n\nNot tested by Scovant Core\n──────────────────────────────────────────────\nObserved WAF access       NOT TESTED\nReal agent tasks          NOT TESTED\nMCP tool execution        NOT TESTED\nWebMCP state parity       NOT TESTED\nMulti-model reliability   NOT TESTED\nRegression stability      NOT TESTED\n\nVerify with real agents:\nhttps://scovant.com/scan?utm_source=scovant-core&utm_medium=cli&utm_campaign=oss\n```\n\nThe headline is **Technical Readiness** (`readiness.technical` — the open\nR2 model, see [`docs/r2.md`](docs/r2.md)): `--min-score` and\n`--require-canonical` gate on it, and a scan whose Technical Readiness has\nno number fails `--min-score`. It is Core's only rating: the five-domain\nStatic Signal Score that 0.18.0 deprecated was removed in 0.19.0 (see the\n[CHANGELOG](CHANGELOG.md) for the migration notes).\n\n## What Core checks\n\n<!-- counts:start — generated by python -m scovant_core.docs --readme; do not edit -->\n69 checks in total: 51 readiness checks across 5 categories (8 experimental) and 18 passive security checks (`CORE-SECURITY-001..018`, 10 experimental). Every check is a diagnostic: none of them carries weight in Technical Readiness, which is computed from the readiness rules. Core implements 56 of the 65 rules; its CLI gathers evidence for 47 today (9 of them only when the site publishes no MCP file). Experimental checks run and report in their own block (see below).\n<!-- counts:end -->\n\nThe readiness checks:\n\n- **Access & Discovery** (11) — HTTPS reachability, robots.txt, AI crawler\n  policy, training-vs-search crawler separation, sitemap availability and\n  freshness, canonical URLs, indexability, llms.txt, Content-Signal, and\n  (experimental) llms.txt utility (useful links, no misplaced policy text,\n  not a template)\n- **Machine Understanding** (12) — JSON-LD parseability, Organization and\n  WebSite/WebPage entities, Product/Offer structured data, product\n  identifier count, breadcrumbs, metadata quality, heading structure,\n  language declaration, image alt coverage, and (experimental) visible-vs-\n  structured price consistency\n- **Agent Interfaces** (9) — MCP discovery and server-declaration quality,\n  WebMCP static presence and (experimental) tool-declaration quality,\n  OpenAPI discovery, OAuth authorization-server and protected-resource\n  metadata, and (experimental) UCP profile validity and agent discovery\n  surface presence (A2A cards, AI-plugin manifests, agents.json, Agent\n  Skills)\n- **Trust & Commerce** (7) — contact/support, shipping, returns/refund,\n  privacy, terms, `security.txt`, and pricing discoverability\n- **Operability & Efficiency** (11) — server-rendered core content,\n  redirect-chain complexity, cache validators, broken machine-consumable\n  endpoints, agent parse cost, form/control labels, unknown paths return a\n  real 404, rate-limiting (429) is signalled with `Retry-After`, bot-\n  challenge pages are not served as HTTP 200, and (experimental,\n  `--experimental` only) machine-reference integrity and discovery linkage\n\n### Experimental checks\n\nSeven checks ship `experimental`: they evaluate and appear in every report,\nin their own block, until they have been calibrated against real-world\ntraffic and promoted. Like every check, they never affect Technical\nReadiness.\n\n| ID | Title |\n|---|---|\n| `CORE-ACCESS-011` | llms.txt utility |\n| `CORE-INTERFACE-004` | WebMCP tool declaration quality |\n| `CORE-INTERFACE-008` | UCP profile validity |\n| `CORE-INTERFACE-009` | Agent discovery surface presence |\n| `CORE-MACHINE-012` | Visible vs. structured price |\n| `CORE-OPERABILITY-007` | Machine reference integrity |\n| `CORE-OPERABILITY-011` | Discovery linkage |\n\n`CORE-OPERABILITY-007` is additionally gated on the `--experimental` flag\nitself — it is the only check whose gatherer (`reference_integrity`) makes\nany network request at all beyond the ordinary scan, so a plain `scovant\nscan` never resolves an external package registry or DNS name for it. The\nother six evaluate on every scan, reported in their own block.\n\nSee [`docs/checks.md`](docs/checks.md) for the full catalog — every check's\nid, applicable profile, and why it matters — generated straight\nfrom the check registry so it can never drift from what the package\nactually runs.\n\n### Agentic Security & Trust (passive)\n\nThe passive security checks counted above report\npassive, declared/observed security signals — HTTP security headers, HSTS,\nCSP, cookie flags, `security.txt` validity, credential-like values or\ninternal-network references exposed in machine-facing surfaces, privileged\nendpoints advertised to agents, and prompt-injection-shaped content in\n`llms.txt`/MCP tool descriptions. They are never rated and never change\nTechnical Readiness — every scan reports the same\n`PASSIVE SIGNALS ONLY` banner and the same four `NOT TESTED` lines\n(observed authorization, verified agent identity, prompt-injection\nresilience, tool invocation safety). Full boundary, verification-mode\nsemantics, and standards mapping: [`docs/security.md`](docs/security.md#agentic-security--trust-passive-checks).\n\n## What Core does NOT test\n\nCore is a static, unauthenticated scanner. It never opens a browser and\nnever observes real traffic, so it cannot tell you:\n\n- Observed WAF/bot-firewall access\n- Real agent task completion\n- MCP tool execution\n- WebMCP state parity (runtime, not just static presence)\n- Multi-model reliability\n- Regression stability over time\n\n## Standards\n\nScovant Core maps its checks to **AgentReady v1.0** (<https://agentready.org/>, MIT), the open\nbaseline standard for agent-facing website signals. AgentReady defines requirements, not weights;\nCore reports which requirements its checks measure (`metrics.standards.agentready_v1` in every\nreport) and never reproduces any third-party score. Mapping: `docs/standards/agentready.md`.\n\n## Core vs Cloud\n\nScovant Core measures passive, machine-facing signals. Scovant Cloud verifies how real agents actually behave, across providers, browser runtimes, security layers and time.\n\nSee [`docs/core-vs-cloud.md`](docs/core-vs-cloud.md) for the full capability\nmatrix and concrete \"Core can determine / cannot determine / Cloud can\ntest\" examples, and [scovant.com/open-source](https://scovant.com/open-source)\nfor the same comparison as a live, always-current page.\n\nWhich readiness rules read the same signal as each check:\n[`docs/crosswalk.md`](docs/crosswalk.md).\n\n## GitHub Action\n\n```yaml\n- uses: Scovant/scovant-core@v0\n  id: scan\n  with:\n    url: https://staging.example.com\n    min-core-score: '70'     # Technical Readiness rating; no number fails too\n    fail-on: fail\n    allow-private-networks: 'true'\n    trusted-target: 'true'\n```\n\n`@v0` is the moving major tag while the package is pre-1.0 — see\n[`docs/releasing.md`](docs/releasing.md); pin `@v0.24.1` instead for an\nexact, never-moving version. `allow-private-networks` is what makes this\nexample work against a private CI runner scanning its own not-yet-public\nstaging host — see \"Free boundary\" below.\n\nThe action installs itself from the checked-out ref (`pip install\n\"$GITHUB_ACTION_PATH\"` — no PyPI dependency, no version skew between the\ntag you pinned and the code that runs), scans one URL, writes a Markdown\nsummary to the job's Step Summary, uploads the full report (HTML by\ndefault) as a workflow artifact named `scovant-core-report`, and fails the\nstep when the gate you configured trips.\n\n### Inputs\n\n| Input | Description | Default |\n|---|---|---|\n| `url` | Entry URL to scan | *(required)* |\n| `profile` | `auto`\\|`content`\\|`commerce`\\|`saas`\\|`api` | `auto` |\n| `min-core-score` | Fail the step below this Technical Readiness rating, or when it has no number (empty = no gate) | `''` |\n| `fail-on` | `never`\\|`fail`\\|`warn` | `never` |\n| `experimental` | Run the experimental checks too (scope `CUSTOM`) | `false` |\n| `timeout` | Total scan budget in seconds | `60` |\n| `report-format` | `html`\\|`markdown` — the uploaded artifact | `html` |\n| `allow-private-networks` | Allow private/loopback targets (your own staging) | `false` |\n| `trusted-target` | Required (`true`) when `allow-private-networks` is `true`; never honoured for pull requests from forks | `false` |\n| `require-canonical` | Fail the step unless Technical Readiness status is `OK` | `false` |\n| `fail-on-security` | `never`\\|`critical`\\|`high`\\|`medium` — fail the step on a FAILed security finding at or above this severity (a WARN never gates) | `never` |\n\n### Outputs\n\n| Output | Description |\n|---|---|\n| `score` | Technical Readiness rating (0-100, empty when it has no number or was not computed) |\n| `grade` | Technical Readiness grade (empty when there is no grade, e.g. `DEGRADED`) |\n| `pass_count` | Number of PASS findings |\n| `warn_count` | Number of WARN findings |\n| `fail_count` | Number of FAIL findings |\n| `report_path` | Path to the uploaded report file on the runner |\n| `coverage` | Technical Readiness evidence coverage ratio (0.0-1.0; empty when not computed) |\n| `score_status` | Technical Readiness status: `OK`\\|`DEGRADED`\\|`INSUFFICIENT_EVIDENCE` (empty when not computed) |\n| `scan_scope` | Check selection scope: `CANONICAL`\\|`CUSTOM` |\n| `error_count` | Number of checks that errored |\n| `security_critical` | Number of `critical`-severity findings in the Agentic Security & Trust section (FAIL + WARN) |\n| `security_high` | Number of `high`-severity findings in the Agentic Security & Trust section (FAIL + WARN) |\n| `security_fail_count` | Number of FAIL findings in the Agentic Security & Trust section |\n| `security_warn_count` | Number of WARN findings in the Agentic Security & Trust section |\n| `model_id` | Technical Readiness model id, e.g. `R2.1@7389c208c89e` (empty when not computed) |\n\n`pass_count`/`warn_count`/`fail_count` are readiness-only (the Agentic\nSecurity & Trust section is never scored — see `Report.security.scored` —\nso a security finding never changes what those three numbers mean); the\n`security_*` outputs above make the security population visible on its own.\n\n### Scanning private networks\n\n> **WARNING:** Never derive the target URL from untrusted PR input when\n> `allow-private-networks: true`. On a self-hosted runner that combination\n> turns the scanner into an internal-network probe.\n\n`allow-private-networks: true` is honoured only together with\n`trusted-target: true`, and never for pull requests from forks — the\naction exits 2 otherwise. A pull request whose head repository is unknown\n(for example, a deleted fork) is treated as a fork. Take the URL from a\nrepository variable, not from the event:\n\n    with:\n      url: ${{ vars.STAGING_URL }}\n      allow-private-networks: 'true'\n      trusted-target: 'true'\n\n### Free boundary\n\nOne URL, one run, no state, no comparison across runs, no schedule, no\noutgoing notification. For history, regression detection, real-agent\nsimulation, and CI-triggered re-scans across your whole site, see\n[Scovant Monitor](https://scovant.com/pricing?utm_source=scovant-core&utm_medium=github&utm_campaign=oss).\n\n## JSON, Markdown and HTML output\n\n```bash\nscovant scan https://example.com --format json\n```\n\nproduces a versioned JSON report (`schema_version`, `core_version`,\n`ruleset_version`, Technical Readiness in `readiness.technical` with its\nper-rule `technical_outcomes`, every finding with its own evidence) suitable for CI pipelines, matching the published\n[`docs/report.schema.json`](docs/report.schema.json). Combine with\n`--min-score`/`--fail-on` for a CI-friendly exit code, or `--output\nreport.json` to write it to a file. `--fail-on-security\nnever|critical|high|medium` gates independently on the Agentic Security &\nTrust section (exit code `6` — a WARN never gates, only a FAIL at or above\nthe given severity; that section is never scored, so this flag is separate\nfrom `--fail-on`/`--min-score`).\n\n```bash\nscovant scan https://example.com --format markdown --output report.md\n```\n\nrenders the same report as GitHub-flavored Markdown — the Technical\nReadiness headline, findings grouped by status with collapsible evidence — ready to\npaste into a pull request or issue.\n\n```bash\nscovant scan https://example.com --format html --output report.html\n```\n\nrenders the same report as one self-contained HTML document (inline CSS,\nno external resources, no JavaScript) — open it directly in a browser or\nattach it as a CI artifact.\n\n## MCP\n\n```bash\npip install \"scovant-core[mcp]\"\nscovant mcp\n```\n\nstarts a stdio MCP server so an agent host (Claude Desktop, Cursor, or any\nMCP client) can run Scovant Core's passive scan as a tool call instead of a\nshell command. Claude Desktop (`claude_desktop_config.json`) and Cursor\n(`.cursor/mcp.json` or Settings → MCP) both take the same config:\n\n```json\n{\n  \"mcpServers\": {\n    \"scovant-core\": {\n      \"command\": \"scovant\",\n      \"args\": [\"mcp\"]\n    }\n  }\n}\n```\n\n| Tool | Description |\n| --- | --- |\n| `scan_site` | Run all 69 checks against one public URL, return the JSON report |\n| `get_core_score` | Run the scan, return the Technical Readiness summary |\n| `list_checks` | List every check with category, profiles, experimental flag |\n| `explain_check` | Explain one check: why it matters, limitations, Cloud extension, references |\n| `get_finding` | Return one finding from a scan this server already ran (no re-scan) |\n\nEvery tool is passive/static only — the same evidence gathering `scovant\nscan` does (public documents: robots.txt, sitemaps, llms.txt, JSON-LD,\nMCP/OAuth/UCP discovery files), never a browser, never an MCP `tools/call`,\nnever authentication. The server runs one scan at a time and keeps only the\nlast 8 reports in memory for `get_finding` to read back.\n\n### Claude Code plugin\n\n```\n/plugin marketplace add Scovant/scovant-core\n/plugin install scovant@scovant\n```\n\nSee [`claude-plugin/README.md`](claude-plugin/README.md) for the bundled\nskills and their MCP wiring.\n\n## Methodology\n\nFull scoring methodology, the status/confidence model, the coverage floor,\nand rule versioning: [`docs/methodology.md`](docs/methodology.md).\n\n## Security\n\nScovant Core fetches arbitrary public URLs; see\n[`docs/security.md`](docs/security.md) for the network safety model\n(scheme allow-list, SSRF guard, redirect/size/timeout limits). Scanning your\nown private/staging infrastructure needs an explicit opt-in — see\n[`docs/security.md` § Private-network targets (opt-in)](docs/security.md#private-network-targets-opt-in).\nTo report a vulnerability, see [`SECURITY.md`](SECURITY.md) or email\n`security@scovant.com`.\n\n### Community contributions (opt-in)\n\n`--contribute` is off by default. When you pass it, Core sends ONE HTTPS\nPOST, after the scan finishes, to a single fixed Scovant endpoint — a\nmeasurement of the PUBLIC site you just scanned, for the aggregate,\nopt-in community index at\n[scovant.com/research](https://scovant.com/research):\n\n```bash\nscovant scan https://example.com --contribute\n```\n\nWhat is sent (exactly these fields, nothing else):\n\n- `domain` — the scanned site's hostname (no path, no query string)\n- `timestamp` — when the scan completed\n- `core_version`, `ruleset_version`, `ruleset_digest` — which Core build and\n  checklist produced the result\n- `profile`, `profile_confidence`, `profile_detector_version` — the resolved\n  site profile (`content`/`commerce`/`saas`/`api`) and how it was detected\n- `experimental` — whether experimental checks were included\n- `check_statuses` — each check id's status (`PASS`/`WARN`/`FAIL`/`N/A`/`ERROR`)\n- `scan_scope` — `CANONICAL` (only canonical scans are sent)\n- `technical` — Technical Readiness: rating, grade, coverage, status and\n  model id (only a scan whose Technical Readiness status is `OK` is sent)\n- `error_count` — how many checks errored\n\nWhat is never sent: no page HTML, no evidence, no URLs beyond the domain\nitself, no IP address, no filesystem paths, no CLI flags beyond what's\nlisted above. The request carries no cookies and never follows a redirect.\n\nA contribution is a client-provided measurement, and it is treated as one:\nunverified discovery signals only.\nClient-provided scores are never incorporated directly into authoritative Scovant research datasets\n— a contributed domain is independently re-evaluated by Scovant-controlled\ninfrastructure before anything about it is published.\n\n`--contribute` is refused (exit 2) together with `--allow-private-networks`\n— only a target Core itself already confirmed public gets contributed. A\ncontribution never changes the CLI's exit code and never fails the scan;\none line on stderr (`contributed: <domain> (accepted|deduplicated|failed:\n<reason>)`) reports the outcome. See\n[`docs/security.md` § Outbound requests](docs/security.md#outbound-requests)\nfor the full network contract.\n\n## Contributing\n\nSee [`CONTRIBUTING.md`](CONTRIBUTING.md). For how releases are made,\nverified, and pinned, see [`docs/releasing.md`](docs/releasing.md).\n\n## License\n\nApache-2.0. See `LICENSE`.\n"}