Quantum Readiness Scan

eu.quantumreadinessPublished by quantumreadiness.euv0.44.0Updated Nov 7, 2026

Local crypto inventory for developers and AI agents; coverage and limits inside the CBOM.

The publisher's own server: scan.mx Email Diagnostics

VerifiedSTDIODesktop onlyDeveloper ToolsSecurity & Monitoring

Overview

AI-generated overview

Scans a local directory for quantum-vulnerable cryptography and returns findings, coverage limits and a CycloneDX CBOM, fully offline.

What you can do
  • Scan a local directory tree for cryptographic algorithms, weak primitives and CI signing commands, with file and line for each finding
  • List the algorithm families the scanner recognises and how each is classified
  • Export the scan as a CycloneDX 1.6 CBOM that carries its own coverage figures
  • Compare two scans to judge whether their coverage numbers are comparable at all
  • Determine which findings a change actually closed by comparing two saved scans
  • Run a self-seeded control that plants known cryptographic uses into a temporary copy and reports what the scan caught
When to use it
Useful when you need a cryptographic inventory of a codebase for a post-quantum migration or an audit and cannot upload the code. It suits developers and agents asking which code paths sign with what, and teams that must show an auditor what was read and what was not.
Requirements
Runs as a local process over stdio, launched with uvx, so uv needs to be on the PATH. No account, API key or network access is required. A local git executable is used to pin the scanned commit.
Before you install
The scan reads source, configuration, certificates and key files under the given path, so point it only at trees you are allowed to inspect. Quoted lines are masked by default; the full-level option writes lines unmasked, which can expose key material in output files. It is an inventory tool, not a readiness assessment, and it does not score risk or plan migration.

Installation

In SourceWeft

  1. Open Quantum Readiness Scan in the dashboard and add it to a workspace.
  2. Enable the server for the chats that should use its tools.

Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.

Other MCP clients

Follow the launch instructions in the repository.

README

qrp-mcp

A local cryptographic inventory for developers and AI agents that carries verifiable coverage and its own limits inside the CBOM.

Every signature in your wallet, contract and validator rests on elliptic-curve cryptography, and a large quantum computer breaks it. Plenty of tools will tell you what they found. This one also tells you what it read, what it could not read, and which question it is not answering — in the document itself, where an auditor can check it rather than take your word.

An MCP server that scans a local directory for cryptography that Shor's algorithm defeats — secp256k1, Ed25519, BLS, Schnorr, RSA — plus weak primitives and CI signing commands, and classifies each one: broken by a quantum computer, post-quantum, or neither.

Everything runs on your machine. No network calls, no account, no API key, nothing uploaded. A tool that reads your keys' surroundings has no business phoning home, so this one makes zero outbound connections — enforced by a test, not promised in a paragraph. The only process it starts is a local git, to pin what it read, with the scanned repository's own hooks and filters disarmed.

mermaid
flowchart TD    R["Your repository, on your machine, at a commit"] --> Q["qrp-mcp — offline, zero network calls"]    Q --> F["Found<br/>file:line and family"]    Q --> N["Not read<br/>each file with its reason"]    F --> J["scan --out result.json"]    N --> J    J --> O["CBOM (CycloneDX 1.6)<br/>SARIF<br/>closure: what a change closed"]

Need a cryptographic inventory (a CBOM) for a post-quantum migration or an audit, without uploading your code? One command, no install step:

uvx qrp-mcp scan ~/code/my-project --out result.json

What comes back, run on this repository's own test fixtures -- the findings, and next to them what the scan did not read:

text
"verdict": "This scan read 24 of 27 files (88.89%); the remaining 3 (1 of 1, by extension            — .b64 — being 100.0% of them) are listed with a reason each.""summary": { "total_findings": 10, "quantum_vulnerable_count": 6, "pqc_ready_count": 1,             "weak_count": 1, "pqc_readiness": "hybrid_partial", ... }

Why this matters for chains and wallets

Bitcoin and Ethereum authenticate with ECDSA over secp256k1. Solana, Cardano and Polkadot use Ed25519. Ethereum's consensus layer aggregates with BLS12-381. Taproot adds Schnorr.

All four are public-key schemes whose security rests on discrete-log hardness — and all four fall to the same quantum algorithm. The practical consequence is specific: once a public key is exposed, the private key becomes derivable. Reused addresses, on-chain public keys, and long-lived validator keys are where that exposure already exists today.

None of this is a prediction about dates. It is an inventory question: which of my code paths sign with what? That question has an answer right now, and this tool gives it.

Quick start

Add it to your MCP client — no installation step, uvx fetches and runs it:

json
{  "mcpServers": {    "qrp": {      "command": "uvx",      "args": ["qrp-mcp"]    }  }}

Then ask your agent:

Scan ~/code/my-protocol for quantum-vulnerable cryptography.

As a Claude Code plugin

The same server, packaged with a skill, so there is no config file to edit:

/plugin marketplace add StanimirTenev/qrp-mcp/plugin install qrp@quantumreadiness

Then /qrp:pqc-scan in any project. Both routes need uv on your PATH, since uvx is what fetches and runs the server.

Without an agent: write the result to a file

uvx qrp-mcp scan ~/code/my-protocol --out result.json

This produces the same result as the scan_repo tool, written to a file you can read before it goes anywhere. Nothing is sent. By default (from 0.40.0, as cbom since 0.16.0 and the tools) the quoted line is masked: everything in it but the algorithm name is starred out. --level full writes the line as it is, and --level trimmed removes the line altogether; all three keep each file and line number. The SHA-256 of the written bytes is printed, so anyone you send the file to can quote back exactly what they received.

That digest is the file's integrity, and the file holds its read times, so two runs over one commit print different ones. Beside it, findings sha256 is the fingerprint of the findings alone (findings_fingerprint in the JSON, in SARIF's run properties and in the CBOM as qrp:findings_fingerprint:sha256): the same on every run and at every --level that finds the same, different when a finding is added or removed. Its normalisation rules are written into the output beside it: each finding as family, raw value, classification and severity; each occurrence as category, path, line, family, role and key size; excerpts, confidence, owners, baseline state, mandate clauses, suppressed rows, coverage and the read window left out; both lists sorted, serialised as compact JSON with sorted keys, SHA-256 in hex. It says the result repeats; it says nothing about whether the result is complete.

uvx qrp-mcp cbom ~/code/my-protocol --out cbom.jsonuvx qrp-mcp closure before.json after.json --out closure.json

cbom writes the same CycloneDX document as the export_cbom tool, masked by default because it is the document built to be sent. closure writes the prove_closure verdict for two saved scans, and names both inputs by their SHA-256, so the three files can be tied together by whoever receives them. Both print the SHA-256 of what they wrote.

A control on your own tree

uvx qrp-mcp control ~/code/my-protocol --seed 1 --out control.json

From 0.43.0. The tree is copied to a temporary directory, known cryptographic uses (9 styles) and lines that name an algorithm without using it (7 kinds) are planted into the copy, and the copy is scanned with the same instrument. The result says which planted lines were found, which were missed and which non-uses were reported as uses — robustness on known patterns, for this version. It is not a statement about what your tree contains, and it never makes the coverage claim stronger. scan --control-seed N carries the block in the result. The control.

A source scan against the build

uvx qrp-mcp scan ~/code/my-service --out scan.json      # before buildinguvx qrp-mcp build-gap scan.json ~/code/my-service/bin/publish --out gap.json

From 0.44.0. Of K public-key-bearing packages or modules in the build, the source scan named J; the K - J list; the families on one side only; and a Go binary's DefaultGODEBUG crypto settings as recorded. It reads only tables the toolchain wrote (*.deps.json, .NET metadata names, go version -m, go tool nm), never code, and never a key size from the build — robustness on known patterns, not recall or coverage of the build. Source against build.

What it reads

Every file under the path is either read or named with the reason it was not. The full list of rules, file types and their limits is in What it looks at.

KindRead as
Source codeC and C++, C#, Visual Basic and F#, Go, Rust, Java, Kotlin, Scala and Groovy, Python, JavaScript and TypeScript, Ruby, PHP, Perl, Solidity, Move and Cairo
Scripts.sh/.bash/.zsh/.ksh, .bat/.cmd, PowerShell .ps1/.psm1/.psd1 — algorithms, and signing commands as a pipeline's are
CI/CD pipelinessigning commands (gpg --sign, cosign sign, signtool, jarsigner, codesign, Secure Boot and kernel-module signing), with the key they name
Infrastructure as codeTerraform/HCL, Kubernetes manifests and Helm (.tpl, .gotmpl), Dockerfiles (including the crypto libraries a RUN installs)
TLS, SSH and VPN configurationnginx, Apache, HAProxy, Caddy, Envoy, Istio, Traefik, Ingress-NGINX, Postfix, Dovecot, MySQL, PostgreSQL, Kafka, ZooKeeper, OpenVPN, WireGuard, strongSwan, OpenSSH, openssl.cnf, java.security, Vault, IBM MQ (.mqsc), AWS load-balancer policies, OPC UA
Device configurationFortiOS backups, Cisco IOS and Junos — read in part, and named as read in part with what was and was not read
Windows.reg exports (SCHANNEL), web.config/app.config/applicationHost.config, MSBuild .vcxproj/.props/.targets, WiX .wxs, certreq .inf, .snk strong-name keys
Certificates and keysPEM and DER (.pem, .der, .crt, .cer, .key, .pub, …), PEM inside any text file or source string, .p12/.pfx, Java keystores, SSH keys, authorized_keys, known_hosts, OpenPGP keys and signatures, JWKS, BIND DNSSEC key and zone files, Apple .plist
Manifests and lockfilesthe dependencies that bring cryptography in, by ecosystem (npm, PyPI, Cargo, Go, Maven/Gradle, NuGet, RubyGems, CocoaPods, SwiftPM, deb/apk/rpm in a Dockerfile)
Not read, on purposedocumentation (.txt, .md, .rst, .pod), binaries and images — counted and named, never silently left out

Coverage on three public repositories

What coverage.scope says on three trees this project did not write, measured on 4 Nov 2026 with the code of this release (the repositories at OpenSSH 7fe3b24, certbot 56ee049, Vault 41e571b). coverage_pct is the share of the files present that were read; read_in_full_pct leaves out the files read only in part (a device configuration, a certificate block that did not parse).

RepositoryFiles presentReadcoverage_pctRead in partread_in_full_pctFindingsWeak
OpenSSH87374184.88%584.31%7054
certbot1,25085068.00%068.00%3928
Vault9,2815,43458.55%958.45%7462

These are reading figures, not detection figures. How well the rules find what is there is a different question; the measurements made of it, each with its date and version, are in How it is measured, and no recall or precision figure is cited here as current.

Documentation

What it is not

It reads source, configuration, CI pipelines, infrastructure-as-code, Kubernetes manifests, build files, certificates and key inventories. It does not read documentation, binaries or images; build-gap reads only the name tables a toolchain wrote into a build, never its code.

Every file under the path is accounted for in one of four ways: scanned, unreadable, skipped because the tool does not claim that type — counted by extension, so the coverage figure has a base, and from 0.27.3 named one by one in the coverage block (not_examined → paths) — or a link not followed, named in symlinks_not_followed. files_scanned + unreadable_files + files_skipped_by_type plus the linked files always equals files_present; until 0.34.0 this sentence said three ways and left the links out. A directory the scan cannot enter or list is named in unreadable_directories; its files cannot be counted, so the scan then says it cannot account for every file instead of claiming it read them all. A scan that read seven files out of nine is a different report from one that read seven out of four hundred, and only one of them is worth trusting.

A free inventory tool, not a readiness assessment. It deliberately does not do:

  • risk scoring or prioritisation,
  • migration planning — a replacement names what a finding becomes, not when or in what order,
  • network or host scanning, or reading a system certificate store,
  • tracking change over time — prove_closure compares two scans you give it; nothing keeps a history.

Those live in the Quantum Readiness Platform, the product this tool is extracted from. Nothing here is crippled to push you there — what it does, it does completely.

It also does not tell you that you are about to be hacked. It tells you what you are using.

License

Apache-2.0.

Source: README.md at commit 61a6f8d

Tools

6

scan_repo

Inventory the cryptography inside one local directory tree, file by file. Reads source, configuration (nginx.conf, sshd_config, .ini, .toml), CI pipelines, Terraform and Kubernetes manifests under `path`. Returns each algorithm found with its file and line, the mathematical family and standing of every post-quantum scheme, and a coverage count. Use this to answer what a specific project on this machine actually uses. Do not use it to ask whether this server knows a given algorithm, or to explain how one is classified without scanning anything -- `list_algorithms` answers that from the same table and reads no files. It is also the wrong tool for a network endpoint, a running host or a certificate store: it opens files on disk and nothing else. Coverage is reported as a fraction with a base. `files_scanned + unreadable_files + files_skipped_by_type + the linked files in symlinks_not_followed == files_present`; a link is not followed and is named, not read. A file that could not be opened is listed, never counted as scanned, because no findings in a file nobody read is not the same as a file that is clean. Files skipped because this tool does not claim their type are counted by extension, so the reader can judge the boundary rather than assume past it. The owner's own settings apply and are reported, never silent: a `.qrp.toml` at the root (its excludes are listed under `coverage.not_examined` as `excluded_by_config`; its baseline marks rows new or baselined), and `qrp:ignore <family> <reason>` comments, whose rows move to `suppressed` with the reason and are counted in `coverage.suppressed`; a marker past its `until=YYYY-MM-DD` no longer applies and is listed as expired. Cost scales with the size of the tree, so a large monorepo takes proportionally longer; there is no cache and no partial mode. Quoted lines are masked by default. Reading happens on this machine,

Parameterspathrequiredlevelprofile

list_algorithms

List every algorithm family this server can recognise, and how each is classified. Returns the whole table: family name, classification (classical and quantum-vulnerable, post-quantum, symmetric, hash, or deprecated) and the kind of use it stands for. Reads no files and takes no arguments. Use this to check coverage before trusting a scan -- whether a scheme the project depends on is one this server knows at all -- or to explain a classification without scanning. To find what a particular directory uses, use `scan_repo` instead; this tool never looks at a codebase. An algorithm absent from this table is reported as `unknown` by a scan, which is not the same as absent from the code.

Takes no parameters.

export_cbom

Scan one directory and return a CycloneDX 1.6 CBOM that carries its own coverage. Same reading as `scan_repo`; a different document. Use this when the result has to leave the machine -- an auditor, a customer, a pipeline artefact -- and `scan_repo` when a person or an agent is going to read it here. What the document carries beyond the components: `compositions.aggregate` states how complete the list is in the schema's own vocabulary, `complete` only when every file present was examined; `properties` carries the whole coverage block flattened, including every file not examined with its reason; and each asset carries `evidence.occurrences` with file, line and matched text. The coverage block travels as `properties` because the CycloneDX root object is `additionalProperties: false` and the format has no field for it. That is the point of emitting it this way rather than a limitation to work around. The serial number is derived from the two pins and a digest of the findings, not from where the tree sits, so two runs of the same code over the same corpus that find the same things share it and a different result does not. The timestamp is the tree's commit time (or SOURCE_DATE_EPOCH), so two runs over one unchanged tree give the same bytes; the read window stays in the scan result. The matched text in `evidence.occurrences` is masked by default, for the reason given on `scan_repo` and one more: this document is the one built to be sent. An auditor needs the algorithm, the file and the line; the contents of the line are not part of the claim being made.

Parameterspathrequiredlevel

compare_coverage

Say whether two scans produced numbers that can be compared at all. Two coverage percentages can differ because the estate moved, because the instrument moved, or because the corpus was collected differently, and the percentages show none of the three. This reads the pins and conditions in both blocks and answers with one of three verdicts. `comparable` means nothing that moves the number differs. `not_comparable` lists which conditions differ, each with what it means, so the reader knows whether to re-run, re-clone or ignore it. `unestablished` means the blocks do not carry enough to decide -- an unpinned corpus, or an emitter that names no commit -- which is a different situation from a known difference and has a different repair. Use it before putting two coverage figures in one table. Do not use it to compare findings; it reads conditions, not results.

Parametersfirstrequiredsecondrequired

prove_closure

Say which findings a change actually closed, by comparing two saved scans of one tree. First it decides whether the two runs can be compared for closure at all: the same instrument commit, version, rules, file types and exclusions, both trees pinned to a commit and clean, both results quoting lines at the same level. The trees themselves may differ -- that difference is what is measured. If the runs cannot be compared, nothing is reported as closed and the repair is named. Only then does it match every occurrence without its line number: `closed` (present before, absent from every file the second run read), still open (and how many only moved lines), `relocated` to another path (renamed or moved, not fixed), `changed` (gone from a file in which the second run finds the same family again -- not closed), `removed` (the whole file is gone from the second tree -- not counted as closed), moved into or out of test code, `new`, and `unverifiable` (in a file the second run did not read). A file the second run could not open is never counted as fixed. To keep the verdict as a file that names the two scans it judged, run `qrp-mcp closure BEFORE AFTER --out FILE`. Use it after a fix, to evidence the fix. Do not use it to compare coverage figures between two estates -- `compare_coverage` answers that. It reads two local files and nothing else.

Parametersafterrequiredbeforerequired

run_self_seeded_control

Plant known lines into a temporary copy of a directory, scan the copy, and say what the scan did with each: robustness on known patterns. 27 cryptographic uses in 9 styles (direct calls, aliased names, names built from pieces, calls split over lines, shell commands in strings, cert-manager, Terraform, Java properties, UTF-16 without a byte-order mark) and 18 lines that name an algorithm without using it (switched-off flags, deny lists, log strings, variable names, comments, a JWKS key label, an sshd_config removal list) per tree with one language. Returns `self_seeded_control` -- counts by style, by decoy class and by confidence, the seed, the harness digest -- and `items`, where each line went and its outcome. Behaviour beyond the annotations: it writes the copy to a temporary directory and removes it afterwards; nothing in `path` changes and nothing leaves the machine. Use it to learn which styles this instrument's silence may be relied on in this tree. Do not use it to inventory the tree -- that is `scan_repo` -- and do not read its counts as a statement about the tree's own cryptography: the denominator is what was planted, and the figure never makes `claims.control.held` true.

Parameterspathrequiredseed

Version history

38
  1. v0.44.0LatestNov 5, 2026
  2. v0.43.0Nov 4, 2026
  3. v0.42.0Nov 4, 2026
  4. v0.40.1Nov 3, 2026
  5. v0.39.0Nov 1, 2026
  6. v0.38.0Oct 30, 2026
  7. v0.37.0Oct 29, 2026
  8. v0.36.0Oct 24, 2026
  9. v0.35.0Oct 23, 2026
  10. v0.34.0Oct 23, 2026
  11. v0.33.0Oct 22, 2026
  12. v0.31.0Oct 21, 2026
  13. v0.30.0Oct 17, 2026
  14. v0.29.1Oct 13, 2026
  15. v0.29.0Oct 7, 2026
  16. v0.28.0Oct 5, 2026
  17. v0.27.3Oct 2, 2026
  18. v0.27.2Oct 1, 2026
  19. v0.27.1Oct 1, 2026
  20. v0.27.0Sep 28, 2026
  21. v0.26.0Sep 28, 2026
  22. v0.23.0Sep 28, 2026
  23. v0.22.0Sep 27, 2026
  24. v0.21.0Sep 27, 2026
  25. v0.19.0Sep 27, 2026
  26. v0.18.1Sep 27, 2026
  27. v0.18.0Sep 26, 2026
  28. v0.17.0Sep 22, 2026
  29. v0.16.0Sep 21, 2026
  30. v0.14.0Sep 20, 2026
  31. v0.13.1Sep 20, 2026
  32. v0.11.0Sep 19, 2026
  33. v0.10.0Sep 19, 2026
  34. v0.9.0Sep 18, 2026
  35. v0.8.0Sep 18, 2026
  36. v0.7.3Sep 17, 2026
  37. v0.7.2Sep 17, 2026
  38. v0.7.1Sep 16, 2026

Score

90% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 days25 pts
  • Auth declared10 pts

    Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.

  • Tools listedRequired15 pts
  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts

Other Scan integrations