Skip to main content
Glama
mgcrea

@mgcrea/mcp-npm

by mgcrea

@mgcrea/mcp-npm

npm version ghcr

A Model Context Protocol server for the npm registry, built around the thing npm's own tooling makes hardest to automate: configuring trusted publishers. It also covers package intel, dist-tags, deprecation, access, org and team governance, tokens, security advisories, and publishing. Read-only by default — the mutating tools are not registered at all unless you turn them on.

Features

  • Trusted publishing, programmatically. Read, set and revoke the OIDC trusted publisher on a package, or apply one across a batch of packages with a single browser authorization.

  • Works with zero configuration. If npm whoami answers, so does this — it reads the token npm login already wrote to ~/.npmrc, scoped to the registry you are actually talking to.

  • Read-only by default. Write tools are absent, not refused, until NPM_ALLOW_WRITES=1. Everything irreversible additionally needs an explicit confirm: true.

  • Never exits on missing credentials. An unconfigured server still answers, and npm_auth_status tells you exactly what to set.

  • Responses shaped for a context window. A raw packument is megabytes; these are a screen.

  • Native fetch, no runtime dependencies beyond the MCP SDK and Zod.

Related MCP server: npm-registry-mcp

Security

Supply chain. Two runtime dependencies: @modelcontextprotocol/server and zod. No HTTP client, no logging framework. Every transitive dependency would be attack surface on a process holding a live npm token.

Your credentials. The token is read from NPM_TOKEN, a config file, or the entry in ~/.npmrc matching the configured registry — a token for npmjs.org is never sent to a private registry, or the reverse. Nothing is written to disk. One-time passwords are held in memory only, for the life of the process.

Blast radius. With the defaults, this server can only read. With NPM_ALLOW_WRITES=1 it can change what your CI is allowed to publish, move dist-tags, deprecate versions, alter org and team membership, mint and revoke tokens, and publish or unpublish packages. Grant it deliberately.

Token choice matters. A granular access token with Bypass 2FA enabled is rejected by every trusted-publisher write. See Traps worth knowing.

Configure

The server starts with no configuration at all. In that state it registers only the tools that need none — npm_auth_status and npm_audit_dependencies, since npm's advisory endpoint takes no authentication — and npm_auth_status tells you what to set for the rest. It never refuses to start over a missing token, because an MCP server that exits shows up in the client as a bare Connection closed with the explanation swallowed.

Most people need nothing:

npm login        # this server reads the resulting ~/.npmrc entry
npm whoami       # if this answers, you are configured

Variable

Required

Description

NPM_TOKEN

no

Overrides the ~/.npmrc lookup. Needed in Docker and CI.

NPM_REGISTRY

no

Defaults to https://registry.npmjs.org. The .npmrc token is looked up for this host.

NPM_DOWNLOADS_URL

no

Defaults to https://api.npmjs.org. A different host, never authenticated.

NPM_ALLOW_WRITES

no

1 to register the write tools. Off by default.

NPM_OTP_MODE

no

web (default), static, or none. See Two-factor.

NPM_OTP

no

A code. Almost always wrong — see the note in .env.example.

NPM_OTP_TTL_SECONDS

no

How long a confirmed code is reused. Defaults to 300, npm's own window.

NPM_OTP_MAX_USES

no

Calls one code covers. Defaults to 80, npm's own guidance.

NPM_AUTO_OPEN_BROWSER

no

0 to print the URL instead of launching a browser.

NPM_MAX_RETRIES

no

Retry budget for 429/5xx. Defaults to 3.

NPM_BIN

no

Path to npm's npm-cli.js (or an npm executable), for npm_publish. Only needed when npm is not on PATH.

NPM_MCP_CONFIG

no

Path to a JSON config file.

NPM_DEBUG

no

1 to log to stderr.

See .env.example for the annotated list.

Config file

  • The environment wins, field by field. A config file supplies whatever the environment does not, so Docker and CI keep working, and a one-off NPM_ALLOW_WRITES=0 still overrides a file that says true.

  • Keys are camelCase (allowWrites, not NPM_ALLOW_WRITES).

  • Unknown keys are an error, not ignored — a typo'd allowWrite tells you so instead of silently falling back to the environment.

  • Location: $NPM_MCP_CONFIG, else $XDG_CONFIG_HOME/npm-mcp/config.json, else ~/.config/npm-mcp/config.json. An absent file is fine; a malformed one is reported with its path. The variable is NPM_MCP_CONFIG, not NPM_CONFIG, because npm reads its own npm_config_* namespace out of the environment.

  • The server warns on stderr if the file is readable by other users.

Quick start

A. npx

{
  "mcpServers": {
    "npm": { "command": "npx", "args": ["-y", "@mgcrea/mcp-npm"] }
  }
}

B. Docker

docker run --rm -i -e NPM_TOKEN ghcr.io/mgcrea/mcp-npm

C. From source

pnpm install && pnpm build
node dist/cli.js

Inspect the tools

npx @modelcontextprotocol/inspector node dist/cli.js

Two-factor, and why this cannot be fully unattended

npm requires an npm-otp header on all three trusted-publisher endpoints — including the read — and a one-time password lasts about five minutes. A code cannot be configured once at startup and reused: it is dead before anything runs. Fully unattended trusted-publisher configuration is not possible, and npm_auth_status reports that rather than offering a setting that looks like it should work.

What is possible is spending one authorization on many packages. npm's confirmation page has a same-IP cooldown; this server caches the confirmed code for that window (in memory, never on disk) so npm_set_trusted_publisher_batch prompts once for up to 25 packages.

The flow, when npm asks:

  1. A trust call goes out without a code and npm answers 401 with an authorization URL.

  2. The server opens that URL and waits for you to approve it.

  3. The call is retried with the confirmed code, and the code is cached for the window.

Run npm_auth_otp first if you would rather approve the prompt at a moment of your choosing — before a long batch, say. Pass it a code from an authenticator app to skip the browser entirely, or open: false when the browser is on another machine.

Tools

41 tools. W = needs NPM_ALLOW_WRITES=1; ⚠ = also needs confirm: true.

Area

Tools

Auth

npm_auth_status, npm_auth_otp, npm_auth_clear_otp, npm_whoami

Trusted publishing

npm_get_trusted_publisher, npm_set_trusted_publisher W, npm_set_trusted_publisher_batch W, npm_delete_trusted_publisher W

Packages

npm_get_package, npm_get_package_version, npm_list_versions, npm_search_packages

Dist-tags

npm_get_dist_tags, npm_add_dist_tag W, npm_remove_dist_tag W

Downloads

npm_get_downloads, npm_get_version_downloads

Security

npm_audit_dependencies (no credentials needed)

Access

npm_get_package_visibility, npm_list_collaborators, npm_set_package_access W⚠, npm_deprecate_package W

Publishing

npm_publish W⚠, npm_unpublish W

Orgs

npm_list_org_members, npm_list_org_teams, npm_list_org_packages, npm_set_org_member_role W, npm_remove_org_member W

Teams

npm_list_team_members, npm_list_team_packages, npm_create_team W, npm_delete_team W⚠, npm_add_team_member W, npm_remove_team_member W⚠, npm_grant_team_package_access W, npm_revoke_team_package_access W

Tokens

npm_list_tokens, npm_create_token W, npm_revoke_token W

Escape hatch

npm_request

Worked example: trusted publishing across a fleet

The problem this server was written for. You have several packages published from one repo, and npm's UI wants you to configure each by hand.

First, check you can:

npm_auth_status

trusted_publishing_available must be true. If it is not, blockers says why — the usual answers are a bypass_2fa token or 2FA not enabled on the account itself.

See what one package has today:

npm_get_trusted_publisher  package="@mgcrea/mcp-ovh"

This is the call that triggers the browser confirmation, because npm requires an OTP even to read. Approve it once.

Now preview the whole batch — nothing is written:

npm_set_trusted_publisher_batch
  packages=["@mgcrea/mcp-npm", "@mgcrea/mcp-ovh", "@mgcrea/mcp-x"]
  provider="github"
  repository="mgcrea/mcp-npm"
  workflow_filename="ci.yml"
  dry_run=true
  confirm=true

Then drop dry_run. Packages already configured correctly come back as unchanged and cost nothing. Verify against npm's own CLI, which calls the same endpoint:

npm trust list @mgcrea/mcp-ovh

With that in place, CI publishes with no token anywhere:

permissions:
  contents: read
  id-token: write   # this is what OIDC trusted publishing needs
# ...
- run: npm publish --provenance --access public

Traps worth knowing

  1. A "Bypass 2FA" granular token is refused by every trust write (403, pointing at gh.io/npm-gat-bypass2fa-deprecation). Reads keep working, so it only surfaces on the write. Create a token without that option, or use a session token from npm login.

  2. Two-factor must be on the npm account, not just the token. No token setting substitutes.

  3. Several governance reads accept only a session token. npm_list_tokens, npm_list_org_members, npm_list_collaborators and npm_get_package_visibility refuse a granular access token — so a read can fail where the matching write succeeds. This is the failure someone who followed npm's own "use granular tokens" advice will hit.

  4. One trusted publisher per package, and no update endpoint. Changing one is genuinely delete-then-create. npm_set_trusted_publisher owns both steps for a reason: split apart, a failed create after a successful delete leaves the package with no publisher and a broken release pipeline.

  5. workflow_filename is a bare filename. ci.yml, never .github/workflows/ci.yml.

  6. Scoped names are escaped two different ways. /@babel%2fcore for the packument, %40babel%2Fcore for the /-/package/ routes. The wrong one returns 404, which reads like "no such package".

  7. Bulk downloads rejects scoped packages, caps at 128, and cannot do a daily series. The single-package form handles @scope/name fine.

  8. **Deprecating with an empty message undeprecates.**

  9. npm_create_token shows the value once. It is never retrievable again, only revocable.

  10. npm_publish produces no provenance attestation. A CI publish over OIDC does. Prefer it.

  11. npm publishes no rate-limit headers, and documents no per-endpoint numbers — only that 5M requests/month is acceptable. Assume nothing; the batch tool paces itself at 2s.

Troubleshooting

A tool I expected is missing. Call npm_auth_status. An absent tool almost always means missing configuration or NPM_ALLOW_WRITES being off — write tools are not registered at all when it is unset, by design.

Connection closed in the client. Run the binary by hand with the same environment; the error the client swallowed is on stderr.

Every trust call 403s. Read the remedy field on the error. The three causes are a bypass_2fa token, 2FA not enabled on the account, and not being a maintainer.

The browser prompt keeps reappearing. The cached code is being minted for a different npm account than the token belongs to. npm_auth_clear_otp, then check npm_auth_status names the account you expect.

Develop

pnpm install
pnpm lint && pnpm format:check && pnpm typecheck && pnpm test && pnpm build

Check the built server still speaks the protocol and gates what it should:

printf '%s\n' \
  '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"cli","version":"0"}}}' \
  '{"jsonrpc":"2.0","method":"notifications/initialized"}' \
  '{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \
| node dist/cli.js 2>/dev/null | jq -r '.result.tools[]?.name'

Publish

pnpm dlx release-it       # bump, commit, tag
git push --follow-tags    # CI publishes to npm and GHCR from the tag

CI publishes over OIDC trusted publishing with provenance, so no npm token exists anywhere.

License

MIT — see LICENSE.

Available Tools

2 tools
npm_audit_dependenciesnpm: Audit DependenciesA
Read-only

Check a set of package versions against npm's security advisories — the same data npm audit uses, queried directly. Takes a flat map of package name to the versions you have installed, and returns only the packages with advisories against them. Needs no npm token, so it works on an otherwise unconfigured server. The references field is stripped from each advisory: it is about 1.5 KB of markdown links apiece, and url already points at the write-up.

ParametersJSON Schema
NameRequiredDescriptionDefault
dependenciesYesInstalled versions per package, e.g. {"lodash": ["4.17.20"], "minimist": ["1.2.0", "0.0.8"]}. Exact versions, not ranges — an advisory match is computed against the version you actually have.

TDQS

A4.5/5.0
Behavior5/5

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

Beyond the readOnlyHint annotation, the description discloses meaningful behavior: it returns only packages with advisories, it strips the `references` field for size, and the `url` field remains as the pointer to the write-up. It also explicitly notes no token is needed, which is valuable operational context.

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

Conciseness5/5

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

The description is concise and well-structured: it opens with the core function, then explains input format, operational prerequisite, and a notable output transformation. Every sentence contributes useful information without redundancy.

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

Completeness5/5

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

For a one-parameter, read-only tool with no output schema, the description adequately covers what input is expected, what the output will contain (only affected packages), and one important field behavior that would otherwise be a surprise. An agent can confidently invoke this tool without needing more context.

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

Parameters3/5

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

The schema has 100% coverage and already explains the format, gives an example, and warns that exact versions (not ranges) are required. The description's phrase 'flat map of package name to the versions you have installed' simply repeats the schema's meaning without adding new semantics, so the baseline 3 is appropriate.

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

Purpose5/5

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

The description states a specific verb ('Check') and resource ('package versions against npm's security advisories'), and ties it to the familiar `npm audit` command. The topic is clearly distinct from the sibling `npm_auth_status`, which is about authentication state, not dependency auditing.

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

Usage Guidelines4/5

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

It gives clear context: this is a direct query of npm's advisory data, and it requires no npm token, so it works on an unconfigured server. It doesn't explicitly mention the sibling as an alternative, but the sibling's purpose is obviously different, so an agent can infer when to use this tool.

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

npm_auth_statusnpm: Auth StatusA
Read-only

Report what this server can and cannot do: whether a token is configured and where it came from, which npm account it belongs to, whether two-factor authentication is on, whether writes are enabled, and whether a one-time password is currently cached. Call this first when a tool you expected is missing — an absent tool means missing configuration rather than a bug. The trusted_publishing_available field and its blockers list answer, without spending a call, whether the trusted-publisher tools can work at all.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.4/5.0
Behavior4/5

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

The readOnlyHint annotation already signals a safe read. The description adds valuable behavioral nuance beyond that: that a missing sibling tool should be interpreted as a configuration gap, not a bug, and that the `trusted_publishing_available` field can answer capability questions 'without spending a call.' This makes the tool's role and interpretation explicit.

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

Conciseness5/5

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

The description is two sentences, front-loaded with the core reporting function, then gives targeted diagnostic guidance. No wasted words; every sentence adds information about what the tool reveals or when to use it.

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

Completeness4/5

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

For a zero-parameter, read-only status tool, the description covers the main output areas and even names a key field (`trusted_publishing_available`) and its `blockers` list. Slight gap: no full response format is given, and with no output schema, a bit more detail on response shape would make it fully self-contained. Still, the essentials are present.

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

Parameters4/5

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

There are zero parameters, and the input schema is empty, so there is nothing for the description to add at the parameter level. The description correctly focuses on outputs and usage rather than inventing parameter detail. A zero-parameter tool earns the baseline score of 4.

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

Purpose5/5

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

The description begins with a precise verb and object: 'Report what this server can and cannot do,' then enumerates the exact dimensions covered (token configuration, account, 2FA, write access, cached OTP). This is unmistakably an auth/status diagnostic tool and leaves no ambiguity about its role relative to the sibling audit tool.

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

Usage Guidelines4/5

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

It gives explicit guidance: 'Call this first when a tool you expected is missing — an absent tool means missing configuration rather than a bug.' It also instructs when to consult specific output fields, which is actionable. There are no alternatives or exclusions, but the diagnostic context is clear enough to warrant a 4.

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

TDQS

A4.2/5.0
Disambiguation5/5

The two tools have entirely distinct purposes: one reports authentication/configuration state, the other checks package versions against security advisories. An agent cannot plausibly confuse them when selecting a tool.

Naming Consistency4/5

Both names share the `npm_` prefix and use snake_case, which makes them feel cohesive. However, `npm_audit_dependencies` is verb-object while `npm_auth_status` is noun-noun, a minor deviation from a fully parallel naming convention.

Tool Count3/5

With only two tools, the server sits at the thin end of the typical range. Each tool is substantive, but an npm-focused server would usually need more surface area to feel well-scoped.

Completeness2/5

The pair gives a useful auth diagnostic and a security audit, but leaves no action path for an agent—there are no package lookup, publish, or remediation tools. The auth status tool also references write and trusted-publisher capabilities that are not exposed, leaving a significant gap for a server called npm.

Maintenance

ActivityNo data
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    Enables npm registry operations from MCP clients like Claude Code and Cursor, with 64 tools for package intelligence, security audits, dependency analysis, org/team management, and write operations like deprecate and unpublish.
    64
    362
    2
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    Grants AI agents real-time access to the NPM registry, enabling package metadata retrieval, version checks, and dependency auditing for up-to-date code generation.
    21
    3
  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides AI assistants with tools to check npm package versions and security heuristics, including version lookups, signal-based analysis, and batch analysis of package.json files.
    15
    AGPL 3.0
  • A
    license
    A
    quality
    C
    maintenance
    Enables AI coding agents to search the npm registry and retrieve package metadata, READMEs, download stats, GitHub details, and usage snippets via the Model Context Protocol.
    9
    21
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mgcrea/mcp-npm'

If you have feedback or need assistance with the MCP directory API, please join our Discord server