Skip to main content
Glama

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.

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:

"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.

Related MCP server: Secure Code Review MCP Server

Quick start

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

{
  "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.json
uvx 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 building
uvx 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.

Kind

Read as

Source code

C 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 pipelines

signing commands (gpg --sign, cosign sign, signtool, jarsigner, codesign, Secure Boot and kernel-module signing), with the key they name

Infrastructure as code

Terraform/HCL, Kubernetes manifests and Helm (.tpl, .gotmpl), Dockerfiles (including the crypto libraries a RUN installs)

TLS, SSH and VPN configuration

nginx, 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 configuration

FortiOS 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 keys

PEM 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 lockfiles

the 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 purpose

documentation (.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).

Repository

Files present

Read

coverage_pct

Read in part

read_in_full_pct

Findings

Weak

OpenSSH

873

741

84.88%

5

84.31%

70

54

certbot

1,250

850

68.00%

0

68.00%

39

28

Vault

9,281

5,434

58.55%

9

58.45%

74

62

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.

Available Tools

5 tools
compare_coverageA
Read-onlyIdempotent

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.

NameRequiredDescriptionDefault
firstYesThe `coverage` block from one scan result.
secondYesThe `coverage` block from another scan result.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive, so safety is covered. Beyond that, the description discloses the full behavioral model: it reads pins and conditions rather than results, returns one of three named verdicts, explains what each verdict means, and flags that 'unestablished' implies a different repair than a known difference. That is genuine context not available from annotations or the schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core purpose, then a rationale paragraph, then a verdict taxonomy, then a use/don't-use instruction. Every sentence earns its place, though the multi-line prose format is slightly longer than strictly necessary for a two-parameter tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only comparison tool with an output schema, the description supplies everything an agent needs: purpose, preconditions (pinned corpus, named commit), the meaning of each verdict, and the decision each verdict implies. Nothing material is left ambiguous.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the two parameters (`first`, `second`) are already documented as coverage blocks. The description reinforces that it reads 'the pins and conditions in both blocks' but adds no syntax or field-level detail beyond the schema. Baseline 3 is appropriate when the schema carries the parameter burden.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a clear verb (compare/say whether) and resource (two scans' coverage blocks), and draws a hard boundary between comparing conditions vs comparing findings. The explicit distinction 'Do not use it to compare findings; it reads conditions, not results' separates it from any result-diffing sibling.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit when-to-use ('before putting two coverage figures in one table') and an explicit when-not-to-use ('do not use it to compare findings'). It even decomposes the three verdicts into decision-relevant repair actions (re-run, re-clone, ignore), which is unusually actionable guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

export_cbomA
Read-onlyIdempotent

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 target, the two pins and a digest of the findings, 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 and coverage window record when each run happened.

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.

NameRequiredDescriptionDefault
pathYesDirectory to scan and export, same argument as `scan_repo`.
levelNoHow much of each matched line to carry in `evidence.occurrences`. Same three levels and the same default as `scan_repo`.masked

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark the tool read-only and idempotent, and the description adds substantial behavioral detail: how coverage is represented in `compositions.aggregate` and `properties`, how serial numbers are deterministically derived, why the coverage block travels as `properties`, and that matched text is masked by default. Nothing contradicts the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but every paragraph earns its place: purpose, usage routing, document contents, format rationale, determinism, and masking policy. It is front-loaded with the core purpose and then layers detail in a logical order with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with a rich output document, an output schema, and annotations covering safety/idempotence, the description is complete: it explains what the document carries, why it is structured that way, when to choose this tool over `scan_repo`, and the masking default. An agent has everything needed to select and invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Input schema coverage is 100%, so the schema already documents `path` and `level` fully. The description adds helpful cross-references to `scan_repo`'s semantics and notes the default level, but it does not significantly extend what the schema already provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence names a specific verb ('Scan'), a specific resource ('one directory'), and a precise output ('CycloneDX 1.6 CBOM'). It explicitly contrasts itself with `scan_repo` ('Same reading... a different document'), so an agent can distinguish this tool from its closest sibling without needing to inspect schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit selection criteria: use this when the result must leave the machine (auditor, customer, pipeline artefact) and use `scan_repo` when a person or agent will read it here. This is direct, unambiguous routing guidance with the named alternative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_algorithmsA
Read-onlyIdempotent

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.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (readOnly, idempotent, non-destructive), the description adds meaningful behavioral detail: it reads no files, takes no arguments, and returns the whole table. It also discloses the important semantics that an algorithm absent from the table is reported as 'unknown' by a scan, which is not the same as absent from the code.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured, front-loaded with the purpose, followed by return value, usage context, and a caveat. Every sentence contributes meaningful information without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter, read-only listing tool with a rich description and an output schema present, everything an agent needs is covered: what it returns, when to use it, when to use the alternative, and the key unknown-classification caveat.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With zero parameters and 100% schema description coverage, the baseline is 4. The description reinforces that the tool takes no arguments and reads no files, which adds a small amount of clarity beyond the empty schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states exactly what the tool does: 'List every algorithm family this server can recognise, and how each is classified.' It clearly identifies the resource (algorithm families) and the action (listing with classification), and it distinguishes itself from the sibling scan_repo by noting it never looks at a codebase.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit when-to-use guidance: check coverage before trusting a scan and explain classifications without scanning. It also names the alternative, scan_repo, and states the condition for choosing it instead ('to find what a particular directory uses'), with a clear exclusion: 'this tool never looks at a codebase.'

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

prove_closureA
Read-onlyIdempotent

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), 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.

NameRequiredDescriptionDefault
afterYesPath to the JSON result of the scan made AFTER the change, same tree, same instrument, same level.
beforeYesPath to the JSON result of the scan made BEFORE the change (`qrp-mcp scan PATH --out FILE`).

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare the safety profile (readOnly, idempotent, non-destructive), and the description adds genuinely new behavioral context: the comparability preconditions, the full closure taxonomy, and edge rules such as 'a file the second run could not open is never counted as fixed.' It even notes it reads only two local files.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core purpose, then preconditions, then the taxonomy. It is fairly long, and the inline CLI aside is somewhat tangential, but every sentence contributes; no filler or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return-value explanation is not required. The description supplies the preconditions, the classification vocabulary, and the guarantee that the verdict names the scans judged, which is everything an agent needs to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so before/after are already documented. The description adds meaning beyond the schema by specifying the two files must share instrument commit, version, rules, file types and level, and that the trees themselves may differ, clarifying what the paths must satisfy to be comparable.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence gives a specific verb and resource ('say which findings a change actually closed') and scopes it ('by comparing two saved scans of one tree'). It explicitly distinguishes itself from the sibling that could be confused with it, compare_coverage.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states when to use it ('after a fix, to evidence the fix') and when not to ('Do not use it to compare coverage figures between two estates'), naming compare_coverage as the alternative. This is exactly the explicit when/when-not/alternative structure.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

scan_repoA
Read-onlyIdempotent

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.

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, but this result does not stay on it: it is returned to a model, which is a place the scanned line has not been before. A secret sharing a line with a finding -- a token in the call that names the cipher -- would travel with it. Masking keeps what a reader needs (the algorithm, the file, the line number, the shape of the call) and removes what nobody asked for. Pass level="full" when the line itself is the thing being examined.

NameRequiredDescriptionDefault
pathYesDirectory to scan, absolute or relative to the working directory: a checked-out repository, a service directory, a config tree. Vendored, build and cache directories (.git, node_modules, vendor, venv, .venv, dist, build, target, .tox, __pycache__, .pytest_cache, .mypy_cache, .ruff_cache) are excluded and do not count toward files_present; the verdict names how many files each one held, .git excepted.
levelNoHow much of each matched line to return. `masked` (the default) keeps the characters that spell the algorithm and stars every other letter and digit; `full` returns the line as written; `trimmed` returns no line at all. File and line number are the same at every level.masked
profileNoWhose rules each `replacement` follows. `nist` (the default) is FIPS 203/204/205. The others read one national document each and say whom it addresses: us-cnsa2 (NSA, US National Security Systems), uk-ncsc, au-ism, ca-cccs, de-bsi, fr-anssi, nl-ncsc, eu-eccg (EU product certification), bg (no Bulgarian guidance found; EU roadmap dates). Detection is identical under every profile.nist

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already carry readOnly/idempotent/non-destructive/closed-world, so the bar is lower, yet the description adds substantial context beyond them: cost scales with tree size with no cache and no partial mode, symlinks are named but never followed, unreadable files are listed but not counted as scanned, and masked lines still leave the machine to a model — a real disclosure about where the data travels. It also states precisely what masking preserves and removes, which is exactly the kind of thing annotations cannot express.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded: purpose in the first line, siblings and exclusions next, then cost and privacy. A few sentences editorialize rather than inform ('no findings in a file nobody read is not the same as a file that is clean') and the coverage-accounting paragraph is dense, but almost every line carries operational weight.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values are covered elsewhere, and the description fills the remaining gaps an agent needs: how coverage fractions reconcile with `files_present`, why skipped extensions are surfaced, why unreadable files are never silently treated as clean, and what the privacy posture of the result is. Nothing material is missing for a read-only scan tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3; the description nevertheless adds a decision rule the schema lacks — pass `level="full"` when the line itself is the thing being examined — and frames `profile` as changing only whose `replacement` rules apply while detection stays identical. It does not add anything for `path` beyond the schema's own exclusion list.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource — inventory cryptography in one local directory tree, file by file — and enumerates the file classes it reads (source, nginx.conf, CI pipelines, Terraform, Kubernetes manifests). It explicitly distinguishes itself from `list_algorithms` (same table, reads no files), so an agent can separate the two without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives positive guidance ('answer what a specific project on this machine actually uses') and multiple explicit exclusions: not for asking whether the server knows an algorithm, not for explaining classification, not for network endpoints, running hosts or certificate stores — 'it opens files on disk and nothing else.' The alternative (`list_algorithms`) is named by name, plus a direct routing rule for `level="full"`.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 1 tool updatev0.35.0
    • Changedscan_repo1 field changed
      • changedInput schema / properties / path / description
        Previous value: -"Directory to scan, absolute or relative to the working directory: a checked-out repository, a service directory, a config tree. Vendored and build directories (.git, node_modules, vendor, dist, build, target) are excluded and do not count toward files_present."New value: +"Directory to scan, absolute or relative to the working directory: a checked-out repository, a service directory, a config tree. Vendored, build and cache directories (.git, node_modules, vendor, venv, .venv, dist, build, target, .tox, __pycache__, .pytest_cache, .mypy_cache, .ruff_cache) are excluded and do not count toward files_present; the verdict names how many files each one held, .git excepted."
  2. 2 tool updatesv0.27.0
    • Addedprove_closure
    • Changedscan_repo1 field changed
      • addedInput schema / properties / profile
        Added value: +{
        +  "default": "nist",
        +  "description": "Whose rules each `replacement` follows. `nist` (the default) is FIPS 203/204/205. The others read one national document each and say whom it addresses: us-cnsa2 (NSA, US National Security Systems), uk-ncsc, au-ism, ca-cccs, de-bsi, fr-anssi, nl-ncsc, eu-eccg (EU product certification), bg (no Bulgarian guidance found; EU roadmap dates). Detection is identical under every profile.",
        +  "enum": [
        +    "nist",
        +    "us-cnsa2",
        +    "uk-ncsc",
        +    "au-ism",
        +    "ca-cccs",
        +    "de-bsi",
        +    "fr-anssi",
        +    "nl-ncsc",
        +    "eu-eccg",
        +    "bg"
        +  ],
        +  "title": "Profile",
        +  "type": "string"
        +}
  3. 2 tool updatesv0.17.0
    • Changedexport_cbom1 field changed
      • addedInput schema / properties / level
        Added value: +{
        +  "default": "masked",
        +  "description": "How much of each matched line to carry in `evidence.occurrences`. Same three levels and the same default as `scan_repo`.",
        +  "enum": [
        +    "full",
        +    "masked",
        +    "trimmed"
        +  ],
        +  "title": "Level",
        +  "type": "string"
        +}
    • Changedscan_repo1 field changed
      • addedInput schema / properties / level
        Added value: +{
        +  "default": "masked",
        +  "description": "How much of each matched line to return. `masked` (the default) keeps the characters that spell the algorithm and stars every other letter and digit; `full` returns the line as written; `trimmed` returns no line at all. File and line number are the same at every level.",
        +  "enum": [
        +    "full",
        +    "masked",
        +    "trimmed"
        +  ],
        +  "title": "Level",
        +  "type": "string"
        +}
  4. 2 tool updatesv0.7.0
    • Addedcompare_coverage
    • Addedexport_cbom
  5. 1 tool updatev0.6.0
    • Changedscan_repo1 field changed
      • addedInput schema / properties / path / description
        Added value: +"Directory to scan, absolute or relative to the working directory: a checked-out repository, a service directory, a config tree. Vendored and build directories (.git, node_modules, vendor, dist, build, target) are excluded and do not count toward files_present."
  6. 2 tool updatesv0.1.0
    • First observedlist_algorithms
    • First observedscan_repo

TDQS

A4.7/5.0

Scored across 5 tools

Disambiguation5/5

Each tool's description explicitly delimits its scope and cross-references the alternatives (export_cbom vs scan_repo, compare_coverage vs prove_closure, list_algorithms vs scan_repo). The export_cbom/scan_repo pair is the closest overlap, but the 'machine-readable artefact vs human/agent reading' distinction is spelled out unambiguously. An agent could select correctly from names alone, and the descriptions remove the remaining doubt.

Naming Consistency5/5

All five names use a consistent snake_case verb_noun pattern (export_cbom, scan_repo, compare_coverage, list_algorithms, prove_closure). The verbs are distinct and meaningful, and no convention mixing appears anywhere in the set.

Tool Count5/5

Five tools is tightly scoped for a cryptographic inventory server: scan, export, algorithm reference, coverage comparison, and closure proof. Each tool covers a distinct operation with no filler, and the set is well within the 3-15 sweet spot.

Completeness4/5

The surface covers the full workflow of scan → export → compare conditions → prove closure, plus a static algorithm reference, with no dead ends in that chain. The one soft gap is that prove_closure reads 'two saved scans' but no tool emits a saveable scan artefact directly (export_cbom emits a CBOM, not a re-loadable scan), so persisting scan output relies on external serialization.

Maintenance

ActivityActive
ResponsivenessSyncing

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Local MCP server that scans code for security issues (secrets, dependencies, configurations, risky patterns) and integrates with GitHub Copilot in VS Code for automated pre-commit reviews.
    -
  • A
    license
    C
    quality
    D
    maintenance
    Security scanner and MCP server that catches dangerous patterns in MCP servers and AI agent projects, such as leaked secrets, shell execution, and prompt-injection text. Runs as both a CLI and MCP server with CI-friendly severity gates.
    2
    1
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Post-quantum readiness for AI coding agents: scans code for quantum-vulnerable cryptography (RSA/ECDH/ECDSA/DH) and returns NIST ML-KEM/ML-DSA/SLH-DSA (and hybrid) migration guidance, with fix verification and dependency checks. Content-based, advisory tools only; runs local (npx @quantakrypto/mcp) or as a hosted OAuth endpoint.
    16
    15
    Apache 2.0