0.0 / 30
What changed in the harness
Selection accuracy 98→100, token cost up 16%, unconfirmed writes 0%→0%.
Category breakdown
Where the score comes from.
Earned points across the four signals Gradable measures. Safety and Legibility are scored out of 30; Economics and Discoverability are scored out of 20.
01Safety
02Legibility
20.4 / 30
03Economics
17.1 / 20
04Discoverability
12.6 / 20
Highest-impact fix
Estimated gain +30 pointsAdd explicit identity and permission preflight tools
Expose machine-readable principal/tenant confirmation and a non-mutating permission check so agents can verify both before destructive actions.
Description evidence
Defects and rewrites.
38 defects found across the exposed tool descriptions. Suggested rewrites make purpose, inputs, boundaries, and returns easier for an agent to understand.
| Tool | Defect types | Suggested rewrite |
|---|---|---|
publish |
name_restates_behavior no_return_description |
Publishes the package at the given path to the npm registry under the specified dist-tag and access level, optionally signing with an OTP or performing a dry run. Returns the published package name, version, and tarball/shasum details, or a preview of what would be published if dryRun is set. |
version |
name_restates_behavior no_return_description |
Bumps the package version at the given path according to the specified bump type (and optional prerelease identifier), updating package.json and creating a git tag unless noGitTag is set. Returns the new version string. |
view |
name_restates_behavior no_return_description |
Fetches metadata for a package from the npm registry, optionally scoped to a single field (e.g. versions, dist-tags). Returns the requested field's value or the full package metadata object. |
search |
name_restates_behavior no_return_description |
Searches the npm registry for packages matching a query string, capped at the given result limit. Returns a list of matching packages with name, description, and version info. |
unpublish |
no_return_description |
Removes a package version (or, with force, the entire package) from the npm registry, optionally authenticating with an OTP. Returns confirmation of what was removed. |
deprecate |
name_restates_behavior no_return_description |
Marks a package version range as deprecated with the given warning message (or clears deprecation if the message is empty), optionally authenticating with an OTP. Returns confirmation of the deprecation change. |
owner |
name_restates_behavior params_unexplained no_return_description |
Lists, adds, or removes owners on the given npm package depending on the action, optionally authenticating with an OTP. The package parameter is the name of the package whose owners are being managed. Returns the resulting list of owners or confirmation of the add/remove. |
dist-tag |
no_return_description |
Lists, adds, or removes a distribution tag on a package depending on the action. Returns the resulting list of dist-tags or confirmation of the add/remove. |
pack |
no_return_description |
Creates a tarball from the package at the given path (or lists the files that would be included if dryRun is set), previewing exactly what publish would upload. Returns the tarball filename and contents or the file list. |
whoami |
no_return_description |
Checks which npm user is currently authenticated (set NPM_TOKEN env var in MCP config if not logged in). Returns the authenticated username. |
init |
no_return_description |
Creates a new package.json in the given directory, optionally under the specified scope. Returns the generated package.json contents. |
audit |
name_restates_behavior no_return_description |
Scans the package at the given path for known vulnerabilities at or above the specified severity level, optionally limited to production dependencies, and can auto-fix issues if requested. Returns a report of found vulnerabilities and any fixes applied. |
outdated |
no_return_description |
Checks the project (or global installs) at the given path for packages with newer versions available. Returns a list of outdated packages with current, wanted, and latest versions. |
ls |
no_return_description |
Lists installed packages in the project at the given path, optionally filtered to a specific package, limited to production dependencies, or scoped globally, with configurable tree depth. Returns the dependency tree or matching package list. |
install |
name_restates_behavior no_return_description |
Installs the specified packages (or all packages from package.json if none given) into the project at the given path, with options to save as dev dependency, pin exact versions, install globally, or preview via dry run. Returns the list of installed/updated packages. |
uninstall |
no_return_description |
Removes the specified packages from the project at the given path, or from the global install if requested. Returns confirmation of the removed packages. |
update |
name_restates_behavior no_return_description |
Updates the specified packages (or all packages if none given) in the project at the given path to their latest semver-compatible versions, optionally scoped globally or previewed via dry run. Returns the list of packages updated with old and new versions. |
access |
params_unexplained no_return_description |
Views or modifies access control on a published package depending on the action (list/get/set/grant/revoke), including access level, team grants, and permissions, optionally authenticating with an OTP. The package parameter specifies which package's access settings to manage. Returns the current access settings or confirmation of the change. |
token |
no_return_description |
Lists active npm access tokens or revokes a specific token by ID, optionally authenticating with an OTP. Returns the list of tokens or confirmation of revocation. |
ping |
no_return_description |
Checks connectivity to the npm registry. Returns the registry's response time and status. |
bugs |
params_unexplained no_return_description |
Looks up the bug tracker URL listed in a package's metadata, given its name. Returns the bug tracker URL. |
repo |
params_unexplained no_return_description |
Looks up the source repository URL listed in a package's metadata, given its name. Returns the repository URL. |
docs |
params_unexplained no_return_description |
Looks up the homepage/documentation URL listed in a package's metadata, given its name. Returns the documentation URL. |
diff |
name_restates_behavior no_return_description |
Compares two package versions (via package/specs) or a local package directory against its registry version, optionally limiting output to changed file names. Returns the diff text or list of changed files. |
pkg |
no_return_description |
Gets, sets, or deletes a field in the package.json at the given path, using the field name (dot notation supported) and a JSON value for set operations. Returns the field's current or updated value. |
fund |
no_return_description |
Shows funding information declared by installed packages in the project at the given path, optionally scoped to one package. Returns the funding URLs and package names. |
dedupe |
no_return_description |
Restructures the dependency tree of the project at the given path to eliminate duplicate package installs, optionally previewed via dry run. Returns the list of changes made or previewed. |
explain |
name_restates_behavior no_return_description |
Traces why the given package is present in the project at the given path by showing the dependency chain that pulled it in. Returns the dependency chain(s) leading to that package. |
sbom |
name_restates_behavior no_return_description |
Generates a Software Bill of Materials for the project at the given path in the specified format (cyclonedx or spdx), optionally limited to production dependencies. Returns the SBOM document. |
profile |
name_restates_behavior no_return_description |
Gets or sets a field (e.g. email, fullname, homepage) on the authenticated npm user's profile, optionally authenticating with an OTP. Returns the current or updated profile field value. |
ci |
name_restates_behavior no_return_description |
Performs a clean install of dependencies strictly from the lockfile at the given path, removing node_modules first, suited for reproducible CI builds. Returns the list of installed packages or an error if the lockfile is out of sync. |
run-script |
name_restates_behavior no_return_description |
Runs a named script from package.json in the project at the given path with optional arguments, or lists available scripts if none is specified. Returns the script's output or the list of available scripts. |
doctor |
no_return_description |
Runs diagnostics on the npm environment (registry connectivity, cache integrity, Node/npm versions, permissions). Returns a health report with pass/fail status for each check. |
cache |
name_restates_behavior no_return_description |
Cleans, verifies, or lists the contents of the local npm cache depending on the action (clean requires force). Returns confirmation of the action or the cache listing/integrity report. |
config |
no_return_description |
Views npm configuration values, either the full list or a specific key (read-only for safety). Returns the requested config value(s). |
prune |
no_return_description |
Removes packages installed in the project at the given path that are not listed in package.json, optionally limited to devDependencies or previewed via dry run. Returns the list of removed packages. |
link |
no_return_description |
Symlinks a local package into the project at the given path for development (or links the current directory globally if package is omitted). Returns confirmation of the created symlink. |
query |
name_restates_behavior no_return_description |
Filters the installed dependency tree in the project at the given path using a CSS-like selector (e.g. ':root > .prod', '#lodash'). Returns the list of matching packages with their metadata. |
Selection evidence
Confusable tool pairs.
5 pairs where similar names or overlapping descriptions may send an agent toward the wrong tool.
| Tool A | Tool B | Confidence | Why they collide |
|---|---|---|---|
repo |
docs |
high | Both return a URL for a package via identical schemas (package name only); a vague request like 'give me the link for package X' or 'where can I learn about this package' could plausibly be routed to either repo or docs. |
bugs |
docs |
medium | Both fetch an informational URL for a package with identical inputs; a task like 'where do I get help with this package's issues' could be misrouted between the bug tracker and docs URL, though 'bug'/'issue' wording usually disambiguates. |
bugs |
repo |
medium | Both return a URL keyed only on package name; a request like 'show me the page for this package on GitHub' could be aimed at the source repo but mistakenly satisfied by the bug tracker URL tool or vice versa. |
unpublish |
uninstall |
high | A generic instruction like 'remove package X' is ambiguous between removing it from the local project (uninstall) and removing it from the npm registry entirely (unpublish); both tools take a package identifier and 'remove' phrasing overlaps heavily. |
unpublish |
deprecate |
medium | Tasks like 'get rid of this broken package version' could be satisfied by either permanently removing it (unpublish) or marking it deprecated with a warning (deprecate), since both operate on package@version specs for similar lifecycle-management intents. |
Compare the field