package-truth
Checks npm packages for existence, latest version, deprecation, known security advisories, license, and age before installation.
Checks NuGet packages for existence, deprecation, known security advisories, license, and age.
Checks PyPI packages for existence, deprecation, known security advisories, license, and age, including support for Python version specifiers.
Checks RubyGems packages for existence, deprecation, known security advisories, license, and age.
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., "@package-truthCheck my package.json for risky dependencies"
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.
Package Truth
Stops coding agents from installing packages that do not exist, are deprecated, or have known vulnerabilities, across npm, PyPI, Go, Maven, Cargo, NuGet and RubyGems.
Language models invent package names. In a USENIX Security 2025 study of 16 code models, 19.7% of the packages they recommended did not exist, and attackers now register those invented names ("slopsquatting"). Package Truth checks every dependency before it is installed and gives each one a verdict an agent can act on:
Verdict | Meaning |
| No such package, no such version, or no version matching the range: do not install |
| The version that would be installed is deprecated or has known advisories |
| Published under 90 days ago or has at most two versions: a possible squat, check before use |
| No problem found in deps.dev at query time (not a security guarantee) |
Give it a whole manifest (package.json, requirements.txt, pyproject.toml, Cargo.toml,
go.mod, Gemfile, *.csproj, pom.xml) and it resolves each range to the version an install
would pick today, checks it, and lists problems first. No account, no key.
Built and maintained by Arhan Canli. Data from deps.dev (Open Source Insights).
Install
Needs Node.js 20 or newer. No account or key.
Claude Code
claude mcp add package-truth -- npx -y package-truth-mcpClaude Desktop: download package-truth-mcp-<version>.mcpb from the latest release and open it. The bundle is signed; verify it with gh attestation verify <file> --repo arhancanli/package-truth-mcp.
Any other client (Windsurf, Zed, Cline, Continue and others), in its MCP config file:
{
"mcpServers": {
"package-truth": {
"command": "npx",
"args": [
"-y",
"package-truth-mcp"
]
}
}
}Docker
docker build -t package-truth-mcp https://github.com/arhancanli/package-truth-mcp.git && docker run -i --rm package-truth-mcpHosted (Streamable HTTP): node src/server.mjs --http serves stateless MCP at POST /mcp (port from PORT, default 3000).
Related MCP server: pkg-oracle
Example
An agent calls check_packages with:
{
"ecosystem": "npm",
"packages": [
{
"name": "express"
},
{
"name": "request"
},
{
"name": "express",
"version": "4.17.1"
},
{
"name": "express",
"version": "99.0.0"
},
{
"name": "left-pad-hallucinated-zz9"
}
]
}and gets back (recorded from the live server on 2026-09-26):
{
"ecosystem": "npm",
"counts": {
"does_not_exist": 2,
"risky": 2,
"verify": 0,
"ok": 1
},
"results": [
{
"name": "express",
"version": "99.0.0",
"latest": "5.2.1",
"verdict": "does_not_exist",
"flags": [
"version_not_found"
],
"note": "Version 99.0.0 was never published. The latest is 5.2.1."
},
{
"name": "left-pad-hallucinated-zz9",
"verdict": "does_not_exist",
"flags": [
"not_found"
],
"note": "The registry has no package with this name. It may be misspelled or hallucinated; do not install it."
},
{
"name": "request",
"version": "2.88.2",
"latest": "2.88.2",
"verdict": "risky",
"flags": [
"deprecated",
"vulnerable",
"no_release_in_3_years"
],
"deprecated_reason": "request has been deprecated, see https://github.com/request/request/issues/3142",
"advisories": [
"GHSA-p8p7-x288-28g6"
],
"license": "Apache-2.0",
"first_published": "2011-01-22",
"latest_published": "2020-02-11",
"version_count": 126
},
{
"name": "express",
"version": "4.17.1",
"latest": "5.2.1",
"verdict": "risky",
"flags": [
"vulnerable"
],
"advisories": [
"GHSA-qw6h-vgh9-j6wx",
"GHSA-rv95-896h-c2vc"
],
"latest_advisory_count": 0,
"license": "MIT",
... (16 more lines)Tools
Tool | What it does |
| Checks every dependency in a manifest file's text (package.json, requirements*.txt, pyproject.toml, Cargo.toml, go.mod, Gemfile, *.csproj, pom.xml). Pinned versions are checked exactly; ranges at the version an install would pick today. Problems are listed first. |
| Checks up to 100 packages in one registry: exists, latest version, deprecated, known advisories, licence, age. Verdict each: does_not_exist, risky, verify (new or tiny: possible squat) or ok. Omit version for the latest. |
| Lists the known security advisories for one package version (latest if omitted): id, title, CVE aliases, CVSS 3 score and link, plus how many affect the latest version. |
How it behaves
Read-only: no tool changes anything outside this process. Manifests are parsed as text; nothing in them is executed or fetched.
Ranges are resolved like the package manager would (npm and Cargo caret, tilde, x and hyphen ranges; PyPI specifiers including
~=and==1.2.*; RubyGems~>). Prereleases are never picked. Maven and NuGet ranges are checked at the latest version and flagged as such.Network: HTTPS only, to the hosts listed in
package.jsonunderfactory.allowHosts, with a deadline, a size cap and bounded retries. Nothing else is contacted, and nothing is logged except unexpected failures (to stderr, without your inputs).Results are compact JSON with a matching output schema. Lists say how many items were left out.
Benchmark
Measured 2026-09-26 with gpt-5.4-mini, 10 fixed tasks graded by fixed checks (bench/tasks.json, raw results in bench/results/).
Server | Correct | Input tokens | Output tokens | Tool calls | Median time |
This server | 10/10 | 13226 | 545 | 10 | 3.3 s |
package-version-check-mcp, the best maintained alternative | 7/10 | 28734 | 531 | 10 | 2.9 s |
Performance
Measured 2026-09-26 from Dubai, home connection against the live upstream, Node 24.19.0 (bench/perf.json, scripts/perf.mjs in the factory).
Call | First call | Repeat | Result size |
check_packages: 5 npm packages (missing, deprecated, vulnerable, clean) | 1556 ms | 1.1 ms | 1,290 chars |
check_packages: 1 PyPI package | 1358 ms | 0.4 ms | 455 chars |
check_packages: 1 Go module | 1721 ms | 1.9 ms | 277 chars |
check_manifest: package.json, 5 entries | 1779 ms | 4.4 ms | 1,270 chars |
check_manifest: requirements.txt, 4 lines | 1526 ms | 0.8 ms | 926 chars |
get_advisories: express 4.17.1 | 2137 ms | 0.3 ms | 462 chars |
First call: a fresh server process, including the TLS connection and the upstream's own time. Repeat: the same call again, answered from the in-process cache, so it shows this server's own overhead.
Tool definitions the model reads on every turn (name, description, input schema): 1,806 characters, against 5,496 for package-version-check-mcp, the best maintained alternative. The full tool list, with the output schemas and annotations clients use to validate results, is 3,899 characters (8,487 for the alternative).
More MCP servers by Arhan Canli
End of Life: Is this version still supported? EOL dates, latest patch and upgrade target for 470+ products.
Internet Standards: RFC sections, status, obsoleted-by chains, errata and IANA registries for coding agents.
Citation Check: Verifies citations: finds fabricated or mismatched references and retractions, returns clean BibTeX.
Drug Label: FDA drug label answers with section citations, RxNorm name resolution, recalls and shortages.
Recall Check: One recall check across CPSC, FDA and NHTSA: match by name, model number, UPC or VIN.
Satellite Imagery: Find the clearest Sentinel-2, Landsat, Sentinel-1 or NAIP scene for any place, with band links.
License
MIT, Copyright (c) 2026 Arhan Canli.
Available Tools
3 toolscheck_manifestCheck a dependency manifestARead-onlyIdempotent
Checks every dependency in a manifest file's text (package.json, requirements*.txt, pyproject.toml, Cargo.toml, go.mod, Gemfile, *.csproj, pom.xml). Pinned versions are checked exactly; ranges at the version an install would pick today. Problems are listed first.
| Name | Required | Description | Default |
|---|---|---|---|
| content | Yes | The file's full text | |
| filename | Yes | File name, e.g. package.json |
Output Schema
| Name | Required | Description |
|---|---|---|
| counts | Yes | |
| results | Yes | |
| skipped | No | |
| ecosystem | Yes | |
| truncated | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, open-world, idempotent, and non-destructive behavior, so the description need not restate those. It adds useful behavioral detail beyond annotations: exact pins are checked exactly, ranges are resolved to today's install-pick version, and problems are listed first.
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?
Two tight, front-loaded sentences: the first names the action and scope, the second states version-resolution semantics and output ordering. Every sentence earns its place with no filler or repetition of the schema.
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 two-parameter read-only tool with a 100%-documented schema, rich annotations, and an output schema, the description provides everything needed to call it correctly: input expectations, version-checking semantics, scope, and result ordering. No critical behavioral gap remains.
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 coverage is 100%, so the baseline is 3, but the description adds value by listing the accepted manifest filename patterns (package.json, requirements*.txt, pyproject.toml, etc.) and clarifying that content is the full file text. This goes beyond the schema's generic 'e.g. package.json' example.
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 clearly states the tool checks every dependency in a manifest file's text and enumerates supported manifest formats, giving a specific verb and resource. It does not explicitly distinguish itself from the sibling check_packages, though the 'manifest file's text' framing makes the scope inferable.
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?
There is no explicit guidance about when to use this tool versus get_advisories or check_packages. The supported-format list implies it is for manifest-file inputs, but no alternative is named or excluded, leaving the agent to infer the decision.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
check_packagesCheck packages before installingARead-onlyIdempotent
Checks up to 100 packages in one registry: exists, latest version, deprecated, known advisories, licence, age. Verdict each: does_not_exist, risky, verify (new or tiny: possible squat) or ok. Omit version for the latest.
| Name | Required | Description | Default |
|---|---|---|---|
| packages | Yes | ||
| ecosystem | Yes | Registry |
Output Schema
| Name | Required | Description |
|---|---|---|
| counts | Yes | |
| results | Yes | |
| ecosystem | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint=false. The description adds valuable behavioral context beyond these: the 100-package limit, the specific checks performed, the verdict categories, and the version-omission behavior. No contradiction with annotations.
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 two sentences with no filler. It front-loads the core action and scope, then lists verdicts, and ends with a concise parameter tip. Every sentence earns its place.
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 annotations, output schema, and the description's coverage of limits, verdicts, and version behavior, the tool is sufficiently specified for an agent to invoke correctly. The only notable gap is the lack of explicit routing guidance relative to sibling tools, but this does not block correct usage.
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 only 50%, with only ecosystem described as 'Registry.' The description compensates by clarifying that packages are checked for existence, latest version, deprecation, advisories, licence, and age, and by explaining that omitting version checks the latest. This adds meaning beyond the raw schema.
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 clearly states a specific action ('Checks up to 100 packages in one registry') and enumerates the checks performed and verdicts returned. It is easy to understand what the tool does, though it does not explicitly differentiate itself from sibling tools like check_manifest or get_advisories.
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?
The title 'Check packages before installing' implies when the tool should be used, and the description adds operational guidance like 'Omit version for the latest.' However, there is no explicit statement of when to prefer this tool over siblings or when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_advisoriesAdvisories for a package versionARead-onlyIdempotent
Lists the known security advisories for one package version (latest if omitted): id, title, CVE aliases, CVSS 3 score and link, plus how many affect the latest version.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| version | No | ||
| ecosystem | Yes | Registry |
Output Schema
| Name | Required | Description |
|---|---|---|
| name | Yes | |
| latest | Yes | |
| version | Yes | |
| advisories | Yes | |
| latest_advisory_count | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, and non-destructive behavior, so the description only needs to add behavioral context. It does so by stating the version default ('latest if omitted') and enumerating the response contents, including advisory metadata and the count affecting the latest version. No contradiction with annotations 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 a single sentence that packs in the action, scope, default behavior, and output contents without filler. Every clause earns its place and the most important scoping detail appears early.
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?
The output schema exists, so return-value details are already structured, and annotations cover the safety profile. The description adds the key usage nuance (version defaults to latest) and the advisory fields returned. A minor gap is that it does not explicitly distinguish when this tool should be preferred over check_manifest or check_packages, but the overall definition is sufficient for correct invocation.
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 coverage is only 33%, so the description carries some burden for parameter meaning. It adds genuinely useful semantics for the version parameter ('latest if omitted') and describes output fields, but it does not clarify the meaning of name or ecosystem beyond what the schema's enum and property name already imply. This is partial compensation rather than full coverage.
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 ('Lists') with a clear resource ('known security advisories') and scopes it to one package version, defaulting to latest when omitted. It also enumerates the returned fields, making its purpose distinct from the sibling tools, which appear to target manifest or package checks.
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?
The description clearly conveys when the tool applies: when a caller needs security advisories for a specific package version, with latest as the default. It does not explicitly state when not to use it or name alternatives, but the context is strong enough for an agent to select it correctly.
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.1.0- First observed
check_manifest - First observed
check_packages - First observed
get_advisories
TDQS
Scored across 3 tools
The three tools are clearly distinct: check_manifest validates dependency files, get_advisories provides detailed advisory info for a specific package version, and check_packages performs bulk registry checks. While both check_manifest and check_packages can surface advisories, their inputs and purposes differ (file text vs. registry list), so ambiguity is minimal.
All tools follow a consistent verb_noun pattern with snake_case: check_manifest, get_advisories, check_packages. The verbs (check, get) are descriptive and the nouns (manifest, advisories, packages) clearly indicate the target.
Three tools is ideal for the server's focused purpose of package verification and security. Each tool serves a distinct need (manifest scanning, bulk checking, advisory lookup) without unnecessary overlap or bloat.
The server covers the core domain comprehensively: manifest validation, bulk package checks (existence, latest, deprecated, advisories, license, age), and detailed advisory queries. For a read-only package truth service, there are no obvious missing operations or dead ends.
Related MCP Connectors
check-package: block malicious npm/PyPI deps before your AI agent installs them. Free, no key.
Verify PyPI and npm packages, symbols, and version diffs against real artifacts. Free, no account.
Verify npm packages before your AI agent installs them: hallucinations, advisories, API drift.
Detect malicious or vulnerable npm packages: registry search, OSV.dev and GitHub advisory lookups
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceEnables users to look up package versions, scan for vulnerabilities, and analyze dependencies across multiple registries (npm, Maven, PyPI, etc.) using exact version recommendations for security.4MIT
- AlicenseNot gradedqualityBmaintenanceAn MCP server that verifies npm and PyPI packages before installation, checking for existence, known vulnerabilities, OpenSSF scorecard, and typosquatting, returning an ALLOW/WARN/BLOCK verdict.MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI coding agents to automatically verify npm packages against the live registry before installation, flagging hallucinated, slopsquatted, or otherwise suspicious packages with risk verdicts.7 npmMIT
- AlicenseAqualityAmaintenanceEnables AI coding agents and CI to vet npm dependencies before they reach the lockfile, flagging hallucinated, slopsquatted, or otherwise risky packages with evidence-backed verdicts.348 npm4MIT