Dep Bouncer
Dep Bouncer is an MCP server that vets npm packages and releases before an AI agent installs or upgrades them, returning ALLOW / REVIEW / BLOCK with evidence and a safe version to use instead.
bouncer_check_package— vet a package/version (orlatest) pre-npm install; verdict, evidence, what npm audit/OSV say, safe alternative.bouncer_check_upgrade— vet a version bump and see what changed (publisher, provenance, install scripts, deps).bouncer_safe_version— newest version in a semver range passing all checks, plus why newer ones were skipped.bouncer_check_manifest— check every dependency in apackage.jsonat the version npm would install today (runs as an MCP Task with live progress).bouncer_review_install_scripts— explain install scripts for up to 15 packages with APPROVE / REVIEW / DENY decisions.bouncer_diff_release— raw human-facing evidence between two versions: files changed, risky new code patterns, deps, provenance.bouncer_replay_incident— replay a real hijack (axios, keyv, chalk, nx, tinycolor) as an agent would have seen it 30 min after publish.Resources —
bouncer://policy(signals, weights, thresholds),bouncer://stats(live latency, errors, verdict totals),incidents://list.safe_installprompt — rules that make an agent call Dep Bouncer before every dependency change and act on the verdict.verdict-cardwidget — visual verdict with evidence panel and one-click "use the safe version".Detects publisher changes, provenance drops, new/changed install scripts, suspicious new deps, malicious code diffs, fresh releases, typosquats/hallucinated names, and OSV advisories.
Also ships an agent guard (Claude Code / Cursor hooks) that intercepts the agent's own
npm i,pnpm add,npx, etc., denying BLOCK and asking on REVIEW.
Vets npm package releases and upgrades before installation by checking registry history, publishers, provenance, install scripts, new or suspicious dependencies, code changes, release timing, name similarity, and known advisories. Returns an ALLOW/REVIEW/BLOCK verdict with evidence and a safe version to install instead.
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., "@Dep Bounceris axios@1.14.1 safe to install?"
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.
Dep Bouncer
npm install, reimagined for AI agents.
![]()
▶ Watch the demo film (2:32): https://youtu.be/w9Ax5KPUGD8
Try it in 30 seconds
Add this live URL as a remote MCP server in your client:
https://dep-bouncer-6ad22414-giberelin-heapify-global-community.app.nitrocloud.ai/mcp
Then ask: "Use the safe_install prompt, then add axios to this project."
Or replay the axios incident directly (Bash / zsh):
curl -X POST 'https://dep-bouncer-6ad22414-giberelin-heapify-global-community.app.nitrocloud.ai/mcp' \
-H 'content-type: application/json' \
-H 'accept: application/json, text/event-stream' \
-H 'mcp-protocol-version: 2025-06-18' \
--data '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"bouncer_replay_incident","arguments":{"incident":"axios"}}}'Works with (tested on the live server):
NitroChat: verdict card rendered (screenshots below).
Claude Code as an MCP client:
claude mcp add --transport http dep-bouncer <URL>; a real session calledbouncer_check_packageandbouncer_replay_incident, reported BLOCK with the evidence, and recommended a safe axios version.Claude Code guard hook: blocked the agent's own
npm installof a non-existent package (guard; Cursor hook config included).Any Streamable-HTTP MCP client via the URL (e.g. Cursor, NitroStudio, ChatGPT developer mode).
Dep Bouncer is an MCP server an AI coding agent calls before it installs or upgrades an npm package. It compares the release with the package's own history (who published it, whether CI signed it, what runs at install time, which dependencies appeared, what code changed) and returns ALLOW / REVIEW / BLOCK with the evidence, plus the version to install instead.
Live MCP endpoint:
https://dep-bouncer-6ad22414-giberelin-heapify-global-community.app.nitrocloud.ai/mcpDemo video (2:32): https://youtu.be/w9Ax5KPUGD8
Track: Developer Tools · Product reimagined: npm (
npm install/npm audit)Built with NitroStack, deployed on NitroCloud.
Related MCP server: pkgtruth
The problem: agents install in seconds, advisories arrive in hours
AI coding agents now run npm install for us, mid-task, from the terminal. npm installs
whatever was published a minute ago, and npm audit only knows about published advisories.
For real hijacks, the free advisory database (OSV) needed hours to catch up:
Hijack | Weekly downloads (Oct 2026) | First OSV entry after publish | What |
axios 1.14.1 (Mar 2026) | 119 M | 2.9 h (MAL-2026-2307) | found 0 vulnerabilities |
keyv 6.0.0 (Aug 2026) | 167 M | 1.7 h (MAL-2026-11524) | found 0 vulnerabilities |
chalk 5.6.1 (Sep 2025) | 496 M | 4.0 h (MAL-2025-46969) | found 0 vulnerabilities |
@ctrl/tinycolor 4.1.1 (Sep 2025) | 4.7 M | 3.8 h (MAL-2025-47141) | found 0 vulnerabilities |
nx 21.5.0 (Aug 2025) | 10.8 M | 18.2 h (MAL-2025-41443) | found 0 vulnerabilities |
Lags measured from the npm registry's publish times and OSV's published field. Two of these
attacks went straight for AI agents: nx's malware ran the victim's claude, gemini and q
CLIs with permission checks disabled, and the keyv worm planted Claude Code SessionStart hooks.
Before / after
Before: agent + npm | After: agent + Dep Bouncer | |
|
| BLOCK: published by a personal account instead of the project's CI; provenance gone; new dependency |
| installs; | BLOCK: new |
| installs | ALLOW: consistent with its own history |
In a real agent (NitroChat, connected to the live server): "Replay the axios incident with Dep Bouncer and tell me what to install instead."

Why this needs MCP
A verdict is not one lookup. For each request the agent's tool call makes Dep Bouncer gather
the registry history (publishers, provenance, publish times), download and diff two tarballs,
look up every newly added dependency, check the name against popular packages, and query OSV.
Then the agent acts on the answer: it installs the safe version, asks the human (REVIEW),
or refuses (BLOCK). The safe_install prompt teaches any agent that loop.
Tools, resources, prompt, widget
MCP surface | What it does |
| Vet a release (or |
| Vet a version bump and show what changed between the two versions. |
| Newest version in a semver range that passes every check, and why newer ones were skipped. |
| Vet every dependency of a package.json at the version npm would install today. Runs as an MCP Task with live progress. |
| npm 12 asks you to approve install scripts but only shows the command. This explains each one: APPROVE / REVIEW / DENY. |
| Replay a real hijack (axios, keyv, chalk, nx, tinycolor) as an agent met it, 30 minutes after publication. |
| Signals, weights and thresholds. |
| Live per-tool calls, errors, p50/p95 latency and verdict totals. |
| The replayable incidents and their OSV lag. |
| Rules that make an agent call Dep Bouncer before every dependency change and act on the verdict. |
| Visual verdict with evidence, the "what other checks say" panel and a one-click "use the safe version". |
Agent guard: no install without a check
Agents forget to call tools. guard/ is a hook for Claude Code
(PreToolUse) and Cursor (beforeShellExecution) that intercepts the agent's own terminal
commands (npm i, pnpm add, yarn add, bun add, npx, pnpm dlx, ...), asks Dep Bouncer
about each package, and denies BLOCK, asks the user on REVIEW, and emits no
permission decision for ALLOW so the host keeps its own permission prompts.
Tested with a real headless Claude Code session asked to
npm install react-codeshift-utils-pro chalk: the hook denied the command ("does not exist on
npm"), the agent verified, did not work around the block, and installed only chalk.
{ "hooks": { "PreToolUse": [ { "matcher": "Bash", "hooks": [
{ "type": "command", "command": "node /path/to/dep-bouncer/guard/dep-bouncer-guard.mjs" } ] } ] } }How it decides
Signal | Looks for | Caught |
| A personal account publishing where CI (npm trusted publishing) always did; a never-seen publisher | axios |
| Previous releases were built and signed by CI; this one was not | axios, nx |
| A new or changed | keyv, nx, tinycolor |
| New dependencies that are days old, run install scripts, copy a popular name, or are never imported (phantom) | axios |
| Code new to this release: obfuscation, process execution, credential paths, exfiltration hosts, wallet hooks, AI-agent abuse ( | chalk, keyv, nx, tinycolor |
| Published in the last 24 h; bursts of versions | all (weak alone) |
| Look-alikes of ~2,400 popular names with few downloads or a recent creation date | typosquats, hallucinated names |
| OSV | anything already reported |
Weights: warn 15, high 35, critical 70. Any critical finding blocks; otherwise the sum
decides: < 30 ALLOW, 30–69 REVIEW, ≥ 70 BLOCK. Versions with incomplete checks require
at least REVIEW and are excluded from safe-version suggestions. Packages that don't exist (hallucinated names),
versions npm removed, and npm's -security placeholders are blocked outright.
Benchmark
npm run bench replays the five hijacks and checks the latest release of the 200 most
downloaded npm packages (presumed healthy; list in bench/packages.txt)
to measure false positives. Latest run (bench/RESULTS.md):
Replayed hijacks: 5 / 5 BLOCK, none of which OSV knew about at the replay time.
200 popular releases: 199 ALLOW, 1 REVIEW, 0 BLOCK. The REVIEW is TypeScript 7, a full rewrite published by a new account: exactly the kind of release a human should glance at. REVIEW means "ask the human", not "block". (An earlier 60-package sample also caught fresh webpack/next/vitest releases as REVIEW; results move as npm does.)
Live endpoint smoke test: node scripts/smoke.mjs calls every tool, resource and prompt on
the deployed server, plus 17 hostile inputs (path traversal, __proto__, broken JSON, oversized
bodies, unknown versions). GitHub Actions runs it hourly and after every push; latest live
run passes all must-checks (p50 0.4 s, p95 2.3 s).
How we got here: the first run flagged webpack and vitest as BLOCK (bundlers rename chunk files every release). Two independent security reviews found 16 issues in the first review and 10 in the second (Oct 17); all findings were fixed. The fixes include line-based code diffs, guard decisions limited to deny/ask while preserving host permission prompts, parsing wrapped commands and subshells, checking every package, API-key support, REVIEW for incomplete checks (excluded from safe-version suggestions), resolving npm aliases, flagging git/URL specs, and always checking packages even when publisher names match. Numbers will move as npm does; CI re-runs the replays on every push.
How it compares (honestly)
Tool | When it acts | Gap Dep Bouncer fills |
| After an advisory is published | Advisories arrived 1.7–18 h after these hijacks |
Socket Firewall Free, Aikido Safe Chain | At install, against the vendor's malware feed | Blocklists: they block once the vendor has flagged a package. Dep Bouncer judges the release from its own history, explains why, and names the version to use. Complementary. |
Cooldowns ( | Hold every release for N hours | Would have held all five hijacks, and every urgent security fix too. Dep Bouncer lets clean fresh releases through and shows cooldown status. |
npm 12 script blocking | Skips install scripts until approved | Approval without explanation; does nothing for code that runs on import (chalk). |
Provenance | Proves where a release was built | keyv 6.0.0 had valid provenance. |
Socket GitHub app | On pull requests | Agents install from the terminal, not through PRs. |
Socket MCP | Scores, fake names | Scores without evidence or a safe version; fake names only. |
Replayed incidents are labelled reconstructions
npm removed the malicious versions. Each replay uses the real last-good release (manifests,
files, publish times, fetched from the registry by scripts/build-fixtures.mjs) plus the
documented changes of the bad release, with benign stand-in code that only mimics the
structure of the attack. Every stand-in file starts with
/* Dep Bouncer reconstruction: benign stand-in, not real malware. */, and every replay result
says what is real and what was reconstructed, with sources. No malware was downloaded or stored.
Architecture
flowchart LR
Agent[AI coding agent] -- MCP --> Tools[bouncer tools / resources / prompt / widget]
Tools --> Bouncer[BouncerService]
Bouncer --> Registry[NpmRegistryService\npackuments, downloads]
Bouncer --> Tarball[TarballService\nin-memory tar.gz, size caps]
Bouncer --> OSV[OsvService]
Bouncer --> Analysis[AnalysisService]
Analysis --> Signals[8 signals] --> Verdict[verdict engine]
Bouncer --> Incidents[IncidentsService\nreplay fixtures]src/
modules/registry/ npm registry, downloads, OSV clients; tar.gz parser; semver; TTL cache
modules/analysis/ signal contract, signals/*, code patterns, name similarity, verdict
modules/incidents/ reconstructed incident fixtures + replay service
modules/bouncer/ MCP tools, resources, prompt; orchestration service
health/ system, npm registry and OSV health checks
widgets/app/verdict-card/ the verdict widget
scripts/ build-fixtures, build-popular, benchmark, copy-assets
test/ node:test suites (signals, parser, replays, semver, ...)NitroStack features used: DI modules and @Injectable, @Tool / @Resource / @Prompt,
@Widget, @RateLimit, @Cache, an interceptor (MetricsInterceptor), guards
(ApiKeyModule + @UseGuards), MCP Tasks (taskSupport, progress, cancellation),
@HealthCheck (system, npm registry, OSV), and the bouncer://stats resource for live
per-tool latency, errors and verdict totals.
Safety: Dep Bouncer never executes package code; tarballs come only from
registry.npmjs.org and are parsed in memory (25 MB compressed, 60 MB extracted, 5,000 files,
path-traversal checks), with byte-budgeted caches, a 4-way download semaphore and redirect
checks. No user data stored; metrics hold no request contents or IPs.
Authentication: the public demo is open on purpose (read-only, public data, rate-limited,
so judges and agents can try it). Set DEP_BOUNCER_API_KEYS=key1,key2 to require an API key
(NitroStack ApiKeyModule; clients send it in MCP _meta.apiKey). See .env.example.
Use it
Any MCP client (Claude, ChatGPT, Cursor, NitroChat): add a remote MCP server with the URL
above. Cursor ~/.cursor/mcp.json:
{ "mcpServers": { "dep-bouncer": { "url": "https://dep-bouncer-6ad22414-giberelin-heapify-global-community.app.nitrocloud.ai/mcp" } } }Then ask: "Use the safe_install prompt, then add axios to this project."
Run locally:
npm install
npm run build
npm test # 220 tests, offline (CI on Node 22 and 24)
npm run bench # replays + false-positive scan (needs network)
npm run dev # stdio, for NitroStudioNo environment variables are required. Optional (see .env.example): MCP_TRANSPORT_TYPE
(stdio / http / dual), PORT, NITRO_LOG_LEVEL.
Limitations and roadmap
Heuristics: a determined attacker can write code that avoids the patterns; the publisher, provenance, script and dependency signals still apply. Tarballs over 25 MB (e.g.
next) skip the code diff and require REVIEW for incomplete coverage.npm only. Next: PyPI, lockfile/CI mode, org policies (e.g. "always REVIEW new publishers").
Team
Harsha B S (team Giberelin, Heapify Global Community) · MIT License · Architecture walkthrough
Available Tools
7 toolsbouncer_check_manifestARead-only
Checks every dependency in a package.json at the version npm would install for its range today (the newest match), e.g. before running npm install in a cloned repo. Runs as an MCP Task with live progress; returns BLOCK/REVIEW first, each with the reason and a safe version.
| Name | Required | Description | Default |
|---|---|---|---|
| includeDev | No | Also check devDependencies | |
| packageJson | Yes | The full text of package.json (up to 90 KB) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint and openWorldHint; the description adds meaningful behavioral context: it runs as an MCP Task with live progress, and the return payload leads with BLOCK/REVIEW entries each carrying a reason and a safe version. That output-ordering and async-execution detail is real value beyond annotations, though it doesn't cover latency, result size, or what REVIEW implies operationally.
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 sentences, front-loaded with purpose and scope, then the usage cue and return contract. No filler, and every clause contributes information the agent needs.
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?
With no output schema, the description carries the return-value burden and does so partially — it names BLOCK/REVIEW, ordering, reasons and safe versions. What BLOCK versus REVIEW means for the caller's next action, and whether the result also lists passing dependencies, is left implicit, which is the only real gap for a tool of this complexity.
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%, with both parameters documented inline (including the 90 KB cap and the includeDev devDependencies behavior). The description adds no parameter-level detail, so the baseline of 3 applies.
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 and resource ('Checks every dependency in a package.json') plus a precise scope qualifier — the version npm would install for the range today, i.e. newest match. This distinguishes it from siblings like bouncer_check_package and bouncer_check_upgrade, which operate on different inputs or questions.
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 a concrete triggering scenario — 'before running `npm install` in a cloned repo' — so the agent knows the intended moment of use. It does not, however, name an alternative sibling or state when not to use it, which keeps it 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.
bouncer_check_packageARead-only
Call this BEFORE npm install <pkg> or adding a dependency. Compares the release with the package's own history (publisher, provenance, install scripts, new dependencies, code diff, name) and returns ALLOW, REVIEW or BLOCK with evidence, what npm audit/OSV say, and a safe version to install instead when blocked.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | npm package name, e.g. "axios" or "@ctrl/tinycolor" | |
| version | No | Exact version, dist-tag or range. Defaults to "latest". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint and openWorldHint; the description goes well beyond that by disclosing the output shape (ALLOW/REVIEW/BLOCK with evidence), the fact that it cross-references npm audit/OSV, and that it recommends a safe alternative version when blocked. It omits latency/rate-limit or data-source freshness caveats, but the behavioral disclosure is substantially richer than the annotations alone.
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 dense sentences, front-loaded with the imperative trigger before the mechanism and return values. Every clause contributes (trigger, comparison basis, verdicts, evidence, audit cross-check, fallback suggestion); the parenthetical signal list is long but information-bearing rather than padding.
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?
With no output schema, the description correctly carries the burden of explaining returns — verdict categories, supporting evidence, audit results, and a suggested safe version. Combined with the 100%-covered input schema and the read-only annotation, an agent has enough to call and interpret the tool correctly; only sibling disambiguation is missing.
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% — both `name` and `version` are documented in the schema, including format examples and the "latest" default. The description adds no parameter-level detail (e.g., how a range behaves vs. a dist-tag), so the baseline 3 applies.
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 names a specific action (compare a release against the package's own history) and enumerates the exact signals inspected — publisher, provenance, install scripts, new dependencies, code diff, name. It clearly positions itself as the broad entry-point check, which implicitly distinguishes it from narrower siblings like bouncer_diff_release and bouncer_review_install_scripts, though it never names them.
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?
"Call this BEFORE `npm install <pkg>` or adding a dependency" gives an explicit, unambiguous trigger for when to invoke the tool. It does not, however, contrast itself with the sibling bouncer_check_upgrade or say when the granular tools (diff_release, review_install_scripts) are preferred over this aggregate check.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bouncer_check_upgradeARead-only
Call this before bumping a dependency from one version to another. Returns the verdict on the new version plus what changed between the two (publisher, provenance, install scripts, dependencies).
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | Version the agent wants to upgrade to | |
| from | Yes | Version currently installed | |
| name | Yes | npm package name, e.g. "axios" or "@ctrl/tinycolor" |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnlyHint, openWorldHint), so the bar is lower. The description still adds real behavioral value by promising a "verdict" and enumerating the change categories surfaced (publisher, provenance, install scripts, dependencies) — exactly the kind of context an agent needs before a version bump.
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 sentences, both earning their place: the first gives the call trigger, the second the return content. The most actionable instruction (when to call) is front-loaded with no preamble.
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?
With no output schema, the description carries the return-value burden and does describe the result (verdict + changed fields). It leaves the verdict's possible values or thresholds undefined, which is a modest gap for a gate-style tool but not a fatal one.
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% and every parameter (name, from, to) is documented in the schema itself. The description restates the from→to relationship but adds no syntax, format, or constraint detail beyond what the schema already provides, so the baseline 3 applies.
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 states a specific verb (check) and a specific resource (a dependency upgrade from one version to another), and the from→to framing distinguishes it from sibling bouncer_check_package, which presumably inspects a single version. It never names the siblings explicitly, so the differentiation is implied rather than stated.
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?
"Call this before bumping a dependency from one version to another" gives an explicit trigger point (pre-upgrade gate), which is clear operational guidance. It does not say when NOT to use it or name alternatives such as bouncer_safe_version or bouncer_check_package, so it stops short of full routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bouncer_diff_releaseARead-only
Raw evidence for humans: what changed between two versions of a package (publisher, provenance, install scripts, dependencies, files added/removed/changed, and risky code patterns new in this release). Use it to explain a REVIEW or BLOCK.
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | Newer version | |
| from | Yes | Older version | |
| name | Yes | npm package name, e.g. "axios" or "@ctrl/tinycolor" |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so the safety profile is covered. The description adds that output is 'raw evidence for humans' and lists the data categories returned, which is useful, but it discloses nothing about cost, rate limits, or bulk/verbosity behavior for a tool that fetches a full package diff.
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 tight sentence, front-loaded with the 'Raw evidence for humans' framing followed by the enumerated contents and the usage call-to-action. No filler, though the parenthetical list is dense.
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?
With no output schema, the description carries the return-value burden and does so by enumerating the diff's contents. Combined with annotations covering the safety profile, an agent has enough to call and interpret it, though the human-vs-machine output distinction could be clearer.
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%, with name/from/to all documented in-schema (including the npm scoped-name example), so the baseline of 3 applies. The description adds no syntax, ordering, or range guidance beyond what the schema already provides.
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+resource (diff two versions of a package) and enumerates the exact dimensions covered: publisher, provenance, install scripts, dependencies, file changes, risky code patterns. It is distinguishable from generic checks, though it never names an overlapping sibling like bouncer_check_upgrade or bouncer_check_package.
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 closing clause 'Use it to explain a REVIEW or BLOCK' gives a real usage context tied to sibling outputs, but there is no when-not guidance and no explicit alternative named among the six siblings that could also surface version-change data. Usage is implied rather than prescribed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bouncer_replay_incidentARead-only
Replays a real npm hijack through Dep Bouncer, as an agent would have met it 30 minutes after publication, before any advisory existed. Incidents: axios (2026), keyv (2026), chalk (2025), nx (2025), tinycolor (2025). The malicious versions were removed from npm, so the bad release is a clearly labelled reconstruction with benign stand-in code.
| Name | Required | Description | Default |
|---|---|---|---|
| incident | Yes | Which incident to replay |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already disclose readOnly and closed-world behavior, and the description adds meaningful context beyond them: the data is a labelled reconstruction with benign stand-in code because the real malicious versions were pulled from npm. It does not cover latency, auth, or exactly what is returned, so not a 5.
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?
Three sentences, front-loaded with the core purpose, and the reconstruction caveat is well placed at the end where it is most relevant. The incident enumeration overlaps the schema enum but the appended years give it enough extra value to be defensible.
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 one-parameter read-only tool this is mostly sufficient, and the simulation framing is clear. However with no output schema the description never indicates what a replay returns, which an agent would reasonably want to know before invoking it.
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% and one enum governs the single parameter, so the baseline is 3. The description restates the enum values and adds years (axios 2026, keyv 2026, chalk 2025, nx 2025, tinycolor 2025), which is contextual flavor but does not change how the parameter is supplied.
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?
Names a specific action (replays a real npm hijack) and the exact artifacts involved, and its scenario/simulation nature cleanly separates it from the check_* siblings. The verb 'replays' is slightly ambiguous about what the caller actually receives, keeping it out of 5 territory.
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 framing 'as an agent would have met it 30 minutes after publication, before any advisory existed' implies the intended scenario (seeing pre-advisory behavior), but there is no explicit when-to-use, when-not-to-use, or pointer to the check_* siblings for real-world verdicts.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bouncer_review_install_scriptsARead-only
npm 12 skips dependency install scripts until they are approved (npm approve-scripts), but only shows the command. Pass the packages it lists; for each one this returns the scripts, why, and APPROVE / REVIEW / DENY. Also useful on npm 11 to see which dependencies run code at install time.
| Name | Required | Description | Default |
|---|---|---|---|
| packages | Yes | Packages whose install scripts need a decision (max 15) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so the safety profile is covered. The description usefully adds that the tool returns the actual scripts, the reasoning behind each verdict, and a tri-state decision value — meaningful behavioral context given there is no output schema.
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 sentences, front-loaded with the npm 12 rationale before the action and the npm 11 fallback use. The npm context sentence is justified because it explains why the tool exists, and nothing is wasted.
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 single-parameter, read-only tool with no output schema, the description covers the workflow trigger, what it returns, and an alternate use case. It leaves minor gaps around output shape and limits (max 15), but those are handled by the schema.
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 the schema already documents the `packages` array with name/version fields. The description only echoes this ('pass the packages it lists') without adding format or selection guidance, so baseline 3 applies.
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+resource: it reviews dependency install scripts and returns scripts, rationale, and APPROVE/REVIEW/DENY verdicts. It differentiates from siblings by narrowly scoping to install-script approval rather than general package checks, though it never names those siblings explicitly.
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 clear triggering context — use it on the packages npm 12's `approve-scripts` lists, and note it works on npm 11 to reveal which deps run install-time code. It does not name alternative sibling tools or state exclusions, so it stops short of a full when/when-not guide.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bouncer_safe_versionARead-only
Returns the newest version of a package (optionally within a semver range such as "^1.14.0") that passes every Dep Bouncer check, and which newer versions were skipped and why. Use it to pick what to install instead of a blocked release.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | npm package name, e.g. "axios" or "@ctrl/tinycolor" | |
| range | No | Semver range, e.g. "^5.0.0". Defaults to any stable version. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint, so the safety and network-touching profile is covered. The description adds genuinely new behavioral detail: it reports which newer versions were skipped and the reason, which an agent could not infer from annotations or schema.
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 sentences with no filler, and the core behavior (what is returned) is front-loaded before the usage hint. Nothing is redundant or buried.
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?
With no output schema, the description carries the burden of explaining returns and does so well (newest passing version plus skipped versions and reasons). It stops short of specifying the exact return shape or how version ordering/range edge cases are handled, which is a minor but real gap.
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 already documented in the schema, including the semver range example and the default of any stable version. The description merely echoes the range concept, adding little beyond the 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?
States a specific verb and resource (returns the newest version of a package) and a precise scope (only versions passing every Dep Bouncer check, optionally constrained by a semver range). This is clearly distinguishable from sibling check-style tools because it resolves to a concrete installable version rather than a verdict.
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?
"Use it to pick what to install instead of a blocked release" gives explicit context for when this tool is the right choice. It does not name a specific alternative sibling (e.g. bouncer_check_upgrade) or state exclusions, so it stops short of full when/when-not guidance.
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 tool update
- Changed
bouncer_check_manifest2 fields changed- changed
Input schema / properties / packageJson / descriptionPrevious value: -"The full text of package.json"New value: +"The full text of package.json (up to 90 KB)" - changed
Input schema / properties / packageJson / maxLengthPrevious value: -200000New value: +90000
7 tool updates
v1.0.0- First observed
bouncer_check_manifest - First observed
bouncer_check_package - First observed
bouncer_check_upgrade - First observed
bouncer_diff_release - First observed
bouncer_replay_incident - First observed
bouncer_review_install_scripts - First observed
bouncer_safe_version
TDQS
Scored across 7 tools
The three check tools (check_package, check_upgrade, check_manifest) target related but distinct contexts (single install, version bump, full manifest), and the descriptions explicitly state when to call each. review_install_scripts, safe_version, diff_release, and replay_incident are clearly separate purposes, though the check trio could still be confused at a glance.
All tools use a consistent bouncer_ prefix with snake_case and mostly verb_noun form (check_package, diff_release, replay_incident, review_install_scripts). safe_version is a minor deviation lacking a verb, but the overall pattern is predictable.
Seven tools is well-scoped for a dependency-security verdict server, with each tool earning its place across pre-install checks, version selection, evidence, and install-script review.
The surface covers the core lifecycle: checking packages, upgrades, and manifests, plus safe-version selection, raw diffs, and install-script review. It lacks obvious config/allowlist management or bulk/CI scan operations, but the primary agent workflows are covered with no hard dead ends.
Maintenance
Related MCP Connectors
Verify npm packages before your AI agent installs them: hallucinations, advisories, API drift.
Check an npm/PyPI package before an AI agent installs it: 5 focused supply-chain tools.
Check exact npm/PyPI upgrades for evidence-backed breaking changes; query APIs and components.
Provide AI-powered real-time analysis and intelligence on NPM packages, including security, depend…
Related MCP Servers
- 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.2 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.3101 npm4MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI coding agents to verify, compare, and safely upgrade npm packages by scoring packages from public signals and sandboxed co-installation, detecting breaking API surface changes, and rewriting code that upgrades break.86 npm8MIT
- AlicenseNot gradedqualityAmaintenanceEnables developers and AI coding agents to vet npm packages before installation by checking existence, lookalike names, package age, install scripts, maintainers, downloads, and advisories, returning GO, RISKY, FAKE, or MISSING. It also scans a project's package.json for worst-first dependency verdicts and can run as a CLI or stdio MCP server.MIT