pkgtruth
This server verifies npm packages before you install, import, or recommend them, flagging hallucinated, slopsquatted, deprecated, abandoned, or otherwise risky dependencies.
check_package— verify one exact npm package name; returns existence and flags impersonation, install-time scripts, deprecation, abandonment, and missing repository/source.check_dependencies— verify up to 50 package names at once, sorted worst-first, useful before writing apackage.jsonor running an install command.Verdicts include
SAFE,CAUTION,DANGER,HALLUCINATED, andUNKNOWN, each with supporting evidence.Network failures return
UNKNOWN, neverSAFE, so a degraded connection cannot silently bypass the safety check.
Provides tools to verify npm package trustworthiness before installation, checking registry existence, security placeholders, impersonation, install scripts, deprecation, adoption, and maintenance status.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@pkgtruthCheck if unused-imports is a hallucinated package before adding it to my project."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
pkgtruth
Ground truth about npm and PyPI packages, for AI coding agents and CI.

Your agent just wrote npm install unused-imports. That package is not the
linter plugin it meant. It is a name an attacker registered because models
kept inventing it — and npm has since replaced it with a security placeholder.
pkgtruth catches that before it reaches your lockfile — as an MCP server the
agent asks, a CLI for CI, a GitHub Action on pull requests, or a Claude Code
hook that denies the install command itself.
Why this exists
Large language models invent package names. Measured across models, 19.7% of generated package names were hallucinated, and when researchers re-ran the prompts, 43% of those names came back every single time.
That reproducibility is the whole attack. An attacker does not need to compromise a maintainer, poison a build server, or find a vulnerability. They watch what models invent, register the name, and wait. The technique is called slopsquatting, and it is already happening in the wild.
The standing security advice is that agents with package-management
capabilities should not install anything without a review gate. pkgtruth is
that gate, in a form an agent can call on its own.
Related MCP server: npm-guardian
Found in the wild
Two names a model plausibly produces, both live on npm today:
Name | What it is | Weekly installs | The real one |
|
| 10 |
|
| Deprecated since 2022, "use the socket.io package instead" | 1,486 |
|
types-node is what you get when a model drops the scope from @types/node.
npm removed it for malicious code in December 2024 and it is still installed
ten times a week.
socket-io is not malicious — it is an abandoned package with a confusable
name. That it takes 1,486 installs a week anyway is the point: a dot and a
hyphen are enough.
PyPI has the same shape without the placeholder:
Name | What it is | Weekly installs | The real one |
| Deprecated shim — its own notice says "use scikit-learn instead" | 321,887 |
|
| A decoy whose only content is "the package named for PyTorch is torch" | 41,026 |
|
Neither is spelled anything like the package it stands in for, which is why pkgtruth also reads what a deprecation notice says: when it names a far more popular package, that name is the evidence.
npx pkgtruth check types-node socket-io
npx pkgtruth check -e pypi sklearn pytorchThose two came from a hand check of twenty names. The systematic version — 242 well-known packages, every plausible garbling of each, regenerated every Monday — lives in SLOPSQUATS.md. Section A there is npm security placeholders alone: names npm purged for malware that are still being installed this week. Weeks in which names enter or leave the list are published as releases, so the releases feed is a way to follow the live list without watching the repository.
Install
As an MCP server (for coding agents)
{
"mcpServers": {
"pkgtruth": {
"command": "npx",
"args": ["-y", "pkgtruth"]
}
}
}Three tools become available:
Tool | Use it when |
| About to add, import, or recommend one dependency ( |
| About to write a |
| About to run |
As a Claude Code hook (the install command itself is stopped)
An MCP tool only helps when the agent remembers to call it. A PreToolUse
hook runs on every shell command instead, and denies npm install, npx,
pnpm add, yarn add, bun add, pip install, uv add, poetry add
and friends when a package they name is hallucinated or dangerous. Add this
to ~/.claude/settings.json (every project) or .claude/settings.json
(one repository, committable):
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [{ "type": "command", "command": "npx -y pkgtruth hook" }]
}
]
}
}Commands that install nothing by name — a bare npm install, git, tests,
npx <bin> of a tool already in node_modules — pass through with no network
call. A blocked command comes back to the agent
as a denial with the evidence, so it can pick the real package instead:
pkgtruth blocked this command: 1 of 2 package(s) must not be installed as-is.
✖ crossenv DANGER — npm replaced this package with a security placeholder (0.0.2-security).
The name was used to publish malicious code. Package is 1 edit(s) from "cross-env",
which has 22,155,059 weekly downloads (15,418x this one). Confirm you meant this
package and not that one.Add --fail-on caution to also stop packages that could not be verified.
npm install -g pkgtruth with "command": "pkgtruth hook" skips the npx
resolution on every call (measured: ~0.2 s per command via npx, ~0.03 s direct). The hook reads tool_input.command from Claude
Code's JSON, or a bare command string from any other agent that pipes one in,
and exits 2 with a permissionDecision: "deny" when it blocks — there is no
environment variable that turns it off, because the agent controls the
environment of the command it runs.
As a Claude Code plugin (server + hook in one install)
/plugin marketplace add hxckya/pkgtruth
/plugin install pkgtruth@pkgtruthThe plugin (plugin/) registers the MCP server and the hook above
together, pinned to the npm release it ships with.
As a CLI (for humans and CI)
npx pkgtruth check express unused-imports # npm (default)
npx pkgtruth check -e pypi requests sklearn # PyPI
npx pkgtruth scan . # every manifest in the directoryscan reads package.json, requirements*.txt and pyproject.toml
(PEP 621 and Poetry), checks each against its own registry, and exits
non-zero when something is blocking, so it drops straight into CI.
As a pull-request gate (GitHub Action)
hxckya/pkgtruth-action (on the
GitHub Marketplace) runs the scan on every pull request, posts one sticky comment with the evidence, and
fails the check on HALLUCINATED or DANGER:
on:
pull_request:
paths: ['package.json', '**/package.json']
permissions:
contents: read
pull-requests: write
jobs:
pkgtruth:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: hxckya/pkgtruth-action@v1This repository gates itself with it — see
.github/workflows/gate.yml, which also proves
the gate can fail by running it against a deliberately bad fixture.
What it checks
Signal | Meaning |
Not in registry | The name is fabricated. Nothing to install. |
npm security placeholder | npm removed malicious code published under this name. |
Impersonates a popular package | A near-identical name with a fraction of the adoption — or a deprecation notice that itself names the package you meant ( |
Yanked (PyPI) | Every file of the latest release was yanked by its maintainer. |
Install-time scripts |
|
Deprecated | Upstream says stop using it. |
Very new / almost no adoption | Days old with single-digit installs. |
No repository | No source to audit. |
Unmaintained | No release in years. |
Verdicts are SAFE, CAUTION, DANGER, HALLUCINATED, or UNKNOWN. Every
one arrives with the evidence behind it — an agent should never have to take
"DANGER" on faith, and neither should you.
Design notes
Network failures never open the gate. If the registry is unreachable, the
verdict is UNKNOWN, never SAFE. A degraded network must not silently turn
a security check into a no-op.
Popular packages are not flagged — measured, not asserted. The false-positive audit runs the detector over the direct dependency closure of 240 well-known packages: 1,523 real packages, 0 blocking verdicts, 0 UNKNOWN after the built-in second pass, and 40 CAUTION (deprecated or unmaintained — true statements, not blocked by default). A gate that cries wolf gets switched off; this one has a number attached.
No build step. Two direct dependencies — the MCP SDK and zod, both only
needed for the server. npx pkgtruth starts immediately.
Limitations
Read these before trusting it:
npm and PyPI only. crates.io, Go modules, RubyGems are not covered yet.
PyPI has no purge marker. npm leaves a
-securityplaceholder where it removed malware; PyPI deletes the project, so a purged PyPI name simply reads asHALLUCINATED. PyPI also has no search API — near-twins are found against a daily snapshot of the top 15,000 projects by downloads, so an impostor of an obscure package will not be caught.Registry metadata only. It does not analyze package source code, so a legitimate-looking package with a malicious payload can still pass.
Not a replacement for
npm auditor Snyk. Those find known CVEs in code you already trust.pkgtruthasks the earlier question: should this package be here at all?New legitimate packages will get
CAUTION. That is deliberate. Newness genuinely is a risk signal; use--fail-on dangerso it does not block.
Options
--json Machine-readable output
--fail-on <level> danger (default) | caution--fail-on caution also blocks packages that could not be verified at all,
since "we could not check" is not a pass.
Exit codes: 0 clean, 1 blocking packages found, 2 usage or runtime error.
Configuration
Variable | Default | Purpose |
|
| Per-request timeout |
|
| Retries for 429/5xx/network errors |
| per-host | Override request pacing |
| npm | Alternate registry |
| npm | Alternate downloads API |
| pypi.org / pypistats.org | Alternate PyPI endpoints |
| hugovk top-pypi-packages | Alternate popularity snapshot for PyPI twins |
|
| Where adoption figures are cached |
| 6 hours | How long a cached figure stays usable |
| unset | Set to |
On speed and rate limits
Adoption figures come from npm's downloads API, which throttles bursts and
cannot batch scoped names — a project with several @scope/pkg dependencies
would spend its whole budget on every scan.
Three things keep that in check: the bulk endpoint resolves all unscoped names in one request, requests to that host are paced serially, and figures are cached on disk for six hours. Weekly download counts move slowly, so a six-hour-old number is no less true.
A warm scan of ~18 dependencies takes about 1.4 seconds. Large scans that
draw 429s from the downloads API leave some packages UNKNOWN on the first
pass; every entry point then re-checks only those names, serially, after a
short pause. In the 1,523-package audit that second pass cleared all of them.
A throttled lookup never becomes SAFE.
Cached figures are keyed by the API they came from, so pointing
PKGTRUTH_DOWNLOADS_API at a private registry never reuses npm's numbers.
Contributing
Issues and pull requests are welcome at github.com/hxckya/pkgtruth.
Two things make a report especially useful: a legitimate package that gets flagged, and a malicious one that slips through. Both are regression tests waiting to be written.
npm test # offline
npm run test:online # includes live registry checksLicense
MIT © hxckya
Available Tools
3 toolscheck_dependenciesGate a whole dependency listARead-onlyIdempotent
Verify many npm or PyPI packages at once — use this before writing a package.json or requirements.txt, or handing a dependency list to a user. All names must belong to one ecosystem per call. Results are sorted worst-first so anything hallucinated or dangerous surfaces at the top. Read-only; batches registry requests and caches adoption figures, so 50 names take a few seconds.
| Name | Required | Description | Default |
|---|---|---|---|
| names | Yes | Package names to verify (max 50), without version suffixes. | |
| ecosystem | No | Registry to check against. Default npm. |
Output Schema
| Name | Required | Description |
|---|---|---|
| total | Yes | |
| results | Yes | Sorted worst-first. |
| blocking | Yes | How many results are HALLUCINATED or DANGER. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, so the safety profile is clear. The description adds useful behavioral context: it mentions sorting results worst-first, batching registry requests, and caching adoption figures, which gives an agent insight into performance and output ordering. Also notes 'Read-only' which aligns with annotations. No contradiction. Slight deduction for not specifying exact output structure, but output schema is present.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and structured, with key information front-loaded: purpose, usage timing, ecosystem constraint, read-only status, and performance caching. Each sentence adds value without redundancy. It is efficient and well-organized.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity, the description covers usage scenarios, constraints, and performance expectations. The output schema provides return details, so the description does not need to elaborate. The annotation set is rich, and the description complements it well, making it complete for an agent to decide when and how to invoke.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both parameters are documented in the schema. The description adds minimal extra beyond the schema: it clarifies that names are without version suffixes and that ecosystem must be uniform, but these are implied in the schema descriptions. Since coverage is high, baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Verify') and resource ('many npm or PyPI packages at once'), and clearly distinguishes from siblings by focusing on batch verification. The mention of 'gate a whole dependency list' adds clarity about the intended use case. It contrasts with check_package (likely single) and check_install_command (likely command-level).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use it: 'before writing a package.json or requirements.txt, or handing a dependency list to a user.' Provides a constraint: 'All names must belong to one ecosystem per call.' Implicitly contrasts with alternatives by focusing on batched verification and noting it batches registry requests.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
check_install_commandCheck the packages an install command would fetchARead-onlyIdempotent
Verify the packages a shell command would install or execute, before running it: npm install …, npx …, pnpm add, yarn add, bun add, pip install, uv add, poetry add and similar, including behind sudo, && chains and sh -c. Extracts the package names (npm and PyPI at once), checks each against its registry, and returns them worst-first. A command that installs nothing by name (a bare npm install from a lockfile, git, npm test, or npx <bin> of a tool already in node_modules) returns total 0 and costs no network call — use check_dependencies on the manifest in that case. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| cwd | No | Directory the command will run in. Lets "npx <bin>" of an already-installed tool be recognised as fetching nothing. Defaults to the server's working directory. | |
| command | Yes | The exact shell command about to run, e.g. "npm install express crossenv" or "pip install -U requests". |
Output Schema
| Name | Required | Description |
|---|---|---|
| total | Yes | |
| command | Yes | |
| results | Yes | Sorted worst-first. |
| blocking | Yes | How many results are HALLUCINATED or DANGER. |
| packages | Yes | What was recognised, per install command. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only and non-destructive hints, and the description's closing 'Read-only' echoes rather than contradicts them (no contradiction). Beyond annotations it adds genuine behavioral context: worst-first result ordering, the zero-network-cost guarantee for no-install commands, and registry-checking behavior. Slightly redundant on 'read-only' since the annotation already states it, but the added cost and ordering disclosures justify a 4.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single dense paragraph that front-loads purpose before listing command types, then behavior, then edge cases and the alternative. Every sentence earns its place — the command list, extraction behavior, worst-first ordering, and fallback routing are all load-bearing. Slightly long as one unbroken block, but nothing is wasteful.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with this complexity (multiple package managers, hidden sudo/&&/sh -c wrapping, edge cases) and an output schema to cover return values, the description is thorough: it covers scope, extraction, ordering, cost behavior, edge cases, and the sibling fallback. The only minor gap is that it doesn't describe the exact output shape, but that is the output schema's job.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both parameters (command, cwd) are already well documented with examples. The description adds some value by explaining cwd's role in recognizing npx-of-installed-tool as fetching nothing, which links the parameter to the behavioral edge case, but it doesn't need to compensate for any schema gap. Baseline 3 with marginal added meaning is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('verify') and resource ('the packages a shell command would install or execute'), then enumerates the exact command types covered (npm, npx, pnpm, yarn, bun, pip, uv, poetry). It differentiates from siblings by explicitly routing the no-install case to check_dependencies, so an agent can pick this tool apart from its siblings without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use guidance: lists the command patterns that install nothing by name (bare npm install from lockfile, git, npm test, npx of an already-installed tool) and directs the agent to 'use check_dependencies on the manifest in that case.' The alternative tool is named and the selection condition is concrete, leaving nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
check_packageCheck one packageARead-onlyIdempotent
Verify a single npm or PyPI package before installing, importing, or recommending it. Returns whether it actually exists, and flags slopsquatting (a low-adoption package impersonating a popular one), names npm removed for malware, install-time scripts, deprecation, and abandonment. Call this whenever you are about to introduce a dependency you have not verified in this session. Read-only; one or two requests to the public registry. A verdict of UNKNOWN means the registry did not answer — retry, never assume safe.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Exact package name as it would be installed, e.g. "express", "@scope/pkg", or for PyPI "requests". No version suffix. | |
| ecosystem | No | Registry to check against. Default npm. |
Output Schema
| Name | Required | Description |
|---|---|---|
| name | Yes | |
| score | No | 0–100 risk score behind the verdict; null when the registry was unreachable. |
| exists | No | |
| ageDays | No | Days since first publish. |
| signals | Yes | |
| summary | Yes | One-paragraph explanation with the suggested real package when there is one. |
| verdict | Yes | HALLUCINATED: no such package. DANGER: do not install as-is. CAUTION: review first. UNKNOWN: could not verify — never treat as safe. SAFE: nothing found. |
| version | No | Latest published version. |
| complete | No | false when a check could not run (rate limit, outage); such a result is UNKNOWN unless already DANGER. |
| pointsTo | No | The package this one's own deprecation notice tells users to install instead, if any. |
| ecosystem | Yes | |
| didYouMean | No | For HALLUCINATED names: real packages with a similar name. |
| repository | No | |
| weeklyDownloads | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/openWorld hints, it discloses concrete runtime behavior: it makes one or two requests to the public registryandar explains the UNKNOWN result semantics with a caution to retry and never assume safe. This is substantial behavioral information that is not encoded in the annotations and materially helps the agent handle edge cases.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact, front-loaded with the action and result, and each sentence adds new information: what it verifies, what it detects, when to use it, network behavior, and UNKNOWN handling. No fluff or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Combined with the rich input schema and annotations, the description covers the core need-to-know: purpose, trigger condition, output facets, edge-case handling, and safety guidance. The agent has enough context to decide when to select this tool and how to interpret its verdict, even without the output schema in view.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already fully documents both parameters (name and ecosystem) with examples, defaults, and constraints. The description adds little beyond repeating 'single package' and 'npm or PyPI', so with high schema coverage the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Verify') with a clear resource ('a single npm or PyPI package') and enumerates the concrete checks performed (existence, slopsquatting, malware-removed names, install-time scripts, deprecation, abandonment). This clearly distinguishes it from the sibling check_install_command and tells the agent exactly what the tool accomplishes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit trigger: 'Call this whenever you are about to introduce a dependency you have not verified in this session.' This clearly states when to use it and the preconditions (before installing, importing, or recommending). However, it does not explicitly name alternatives or when-not-to-use scenarios, so it falls short of a 5.
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.
3 tool updates
v0.2.2- Changed
check_dependencies5 fields changed- added
Input schema / properties / ecosystemAdded value: +{ + "description": "Registry to check against. Default npm.", + "enum": [ + "npm", + "pypi" + ], + "type": "string" +} - changed
Input schema / properties / names / descriptionPrevious value: -"Package names to verify (max 50)."New value: +"Package names to verify (max 50), without version suffixes." - added
Input schema / properties / names / items / maxLengthAdded value: +214 - added
Input schema / properties / names / items / minLengthAdded value: +1 - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "blocking": { + "description": "How many results are HALLUCINATED or DANGER.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "results": { + "description": "Sorted worst-first.", + "items": { + "additionalProperties": {}, + "properties": { + "ageDays": { + "description": "Days since first publish.", + "type": [ + "number", + "null" + ] + }, + "complete": { + "description": "false when a check could not run (rate limit, outage); such a result is UNKNOWN unless already DANGER.", + "type": "boolean" + }, + "didYouMean": { + "description": "For HALLUCINATED names: real packages with a similar name.", + "items": { + "additionalProperties": {}, + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + }, + "type": "array" + }, + "ecosystem": { + "enum": [ + "npm", + "pypi" + ], + "type": "string" + }, + "exists": { + "type": [ + "boolean", + "null" + ] + }, + "name": { + "type": "string" + }, + "pointsTo": { + "description": "The package this one's own deprecation notice tells users to install instead, if any.", + "type": [ + "string", + "null" + ] + }, + "repository": { + "type": [ + "string", + "null" + ] + }, + "score": { + "description": "0–100 risk score behind the verdict; null when the registry was unreachable.", + "type": [ + "number", + "null" + ] + }, + "signals": { + "items": { + "additionalProperties": false, + "properties": { + "detail": { + "description": "One sentence of evidence, written for the agent to relay.", + "type": "string" + }, + "id": { + "description": "Stable machine id, e.g. npm_security_placeholder, impersonates_popular_package, not_in_registry, incomplete_check.", + "type": "string" + }, + "severity": { + "enum": [ + "critical", + "high", + "medium", + "low", + "info" + ], + "type": "string" + } + }, + "required": [ + "id", + "severity", + "detail" + ], + "type": "object" + }, + "type": "array" + }, + "summary": { + "description": "One-paragraph explanation with the suggested real package when there is one.", + "type": "string" + }, + "verdict": { + "description": "HALLUCINATED: no such package. DANGER: do not install as-is. CAUTION: review first. UNKNOWN: could not verify — never treat as safe. SAFE: nothing found.", + "enum": [ + "SAFE", + "CAUTION", + "DANGER", + "HALLUCINATED", + "UNKNOWN" + ], + "type": "string" + }, + "version": { + "description": "Latest published version.", + "type": [ + "string", + "null" + ] + }, + "weeklyDownloads": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "name", + "ecosystem", + "verdict", + "summary", + "signals" + ], + "type": "object" + }, + "type": "array" + }, + "total": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "blocking", + "total", + "results" + ], + "type": "object" +}
- Added
check_install_command - Changed
check_package5 fields changed- added
Input schema / properties / ecosystemAdded value: +{ + "description": "Registry to check against. Default npm.", + "enum": [ + "npm", + "pypi" + ], + "type": "string" +} - changed
Input schema / properties / name / descriptionPrevious value: -"Exact npm package name, e.g. \"express\" or \"@scope/pkg\"."New value: +"Exact package name as it would be installed, e.g. \"express\", \"@scope/pkg\", or for PyPI \"requests\". No version suffix." - added
Input schema / properties / name / maxLengthAdded value: +214 - added
Input schema / properties / name / minLengthAdded value: +1 - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "ageDays": { + "description": "Days since first publish.", + "type": [ + "number", + "null" + ] + }, + "complete": { + "description": "false when a check could not run (rate limit, outage); such a result is UNKNOWN unless already DANGER.", + "type": "boolean" + }, + "didYouMean": { + "description": "For HALLUCINATED names: real packages with a similar name.", + "items": { + "additionalProperties": {}, + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + }, + "type": "array" + }, + "ecosystem": { + "enum": [ + "npm", + "pypi" + ], + "type": "string" + }, + "exists": { + "type": [ + "boolean", + "null" + ] + }, + "name": { + "type": "string" + }, + "pointsTo": { + "description": "The package this one's own deprecation notice tells users to install instead, if any.", + "type": [ + "string", + "null" + ] + }, + "repository": { + "type": [ + "string", + "null" + ] + }, + "score": { + "description": "0–100 risk score behind the verdict; null when the registry was unreachable.", + "type": [ + "number", + "null" + ] + }, + "signals": { + "items": { + "additionalProperties": false, + "properties": { + "detail": { + "description": "One sentence of evidence, written for the agent to relay.", + "type": "string" + }, + "id": { + "description": "Stable machine id, e.g. npm_security_placeholder, impersonates_popular_package, not_in_registry, incomplete_check.", + "type": "string" + }, + "severity": { + "enum": [ + "critical", + "high", + "medium", + "low", + "info" + ], + "type": "string" + } + }, + "required": [ + "id", + "severity", + "detail" + ], + "type": "object" + }, + "type": "array" + }, + "summary": { + "description": "One-paragraph explanation with the suggested real package when there is one.", + "type": "string" + }, + "verdict": { + "description": "HALLUCINATED: no such package. DANGER: do not install as-is. CAUTION: review first. UNKNOWN: could not verify — never treat as safe. SAFE: nothing found.", + "enum": [ + "SAFE", + "CAUTION", + "DANGER", + "HALLUCINATED", + "UNKNOWN" + ], + "type": "string" + }, + "version": { + "description": "Latest published version.", + "type": [ + "string", + "null" + ] + }, + "weeklyDownloads": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "name", + "ecosystem", + "verdict", + "summary", + "signals" + ], + "type": "object" +}
2 tool updates
v0.1.1- First observed
check_dependencies - First observed
check_package
TDQS
Scored across 3 tools
Each tool has a clearly distinct scope: single package, multiple packages, and install command parsing. No overlap in purpose, and descriptions explicitly differentiate when to use each, eliminating ambiguity for the agent.
All three tools follow the consistent 'check_' + object pattern: check_package, check_dependencies, check_install_command. The verb is uniform and the object clearly indicates the target, making the naming predictable and intuitive.
With 3 tools, the server is tightly scoped to package verification and covers the essential granularity levels (single, bulk, command). Each tool serves a distinct need without redundancy, and the small count feels intentional rather than incomplete.
The tool surface covers the full workflow of package verification: checking individual packages, checking dependency lists before manifest creation, and validating install commands. The descriptions also handle edge cases like bare installs and lockfile usage, indicating thoughtful coverage with no obvious gaps.
Maintenance
Related MCP Connectors
Verify npm packages before your AI agent installs them: hallucinations, advisories, API drift.
check-package: block malicious npm/PyPI deps before your AI agent installs them. Free, no key.
Provide AI-powered real-time analysis and intelligence on NPM packages, including security, depend…
Blocks typosquatted or hallucinated npm/PyPI packages before an AI agent installs them.
Related MCP Servers
- AlicenseAqualityFmaintenanceActs as a security checkpoint for AI coding agents by intercepting package installations to verify existence, check against CVE databases, and block vulnerable or hallucinated dependencies before they reach your codebase. Provides seven security tools including pre-install gates, full project audits, safe version recommendations, and deep transitive dependency scanning for npm and PyPI packages.746 npm4MIT
- AlicenseNot gradedqualityCmaintenanceAudits npm packages for supply-chain attacks (typosquatting, malicious install scripts, credential exfiltration) before installation, returning a SAFE/SUSPICIOUS/DANGEROUS verdict.MIT
- AlicenseAqualityDmaintenanceDependency security & health auditing for AI agents with no account or API key required.22MIT

EVIDIQ Lineageofficial
AlicenseNot gradedqualityBmaintenanceDeterministic supply-chain provenance, SBOM/AI-BOM generation, and dependency risk analysis for npm and PyPI packages, with 14 security rules and verifiable reports.1MIT