Skip to content
verify mcp Beta VerifyMCP is currently in beta. If you notice any issues, email [email protected] and we’ll put it right.

Avoid install scripts in your MCP package

What we checked

We looked at your package metadata for install-time scripts: code the package manager runs automatically during installation, before you’ve run a single intentional line. The signal passes when no such scripts are declared. If your package declares one, it’s flagged as an un-assessed risk factor: a hook we could not review. If our scanning provider has since assessed that hook, we record the risk as assessed instead. And if we couldn’t tell either way whether scripts are declared, the signal is unverifiable and scores 0 until we can assess it.

Why it matters

An install script runs with your shell’s permissions the moment a user (or an agent) types install, with no review, no opt-in, often no awareness it happened. That makes it one of the most heavily abused vectors in supply-chain attacks:

  • a hijacked or typosquatted package can exfiltrate environment variables, tokens, or SSH keys from a postinstall hook;
  • the malicious code never appears in the source a reviewer reads at runtime, so it hides in plain sight;
  • because it fires on install, CI machines and developer laptops are exposed before any test or sandbox boundary applies.

A server that needs no install script is strictly safer to add, and consumers increasingly install with scripts disabled by default.

How to fix it

This is primarily an npm/Node concern. Move any work a script was doing into an explicit runtime step or a documented CLI command the user runs deliberately, and delete the install/postinstall/preinstall hooks from package.json:

{
"name": "your-mcp-server",
"scripts": {
  "postinstall": "node ./scripts/setup.js",
  "start": "node ./dist/index.js"
}
}

If a script is genuinely unavoidable (for example, compiling a native addon), keep it minimal, do only what’s strictly necessary, and document in your README exactly what it does and why.

How we re-check

We re-read your package metadata on our next crawl. Once the published version no longer declares install-time scripts, the signal flips to a pass on the following score refresh.

Give this to your AI

Paste this into Claude Code (or any coding agent) from inside your server's repository. It states the failing signal, the outcome we re-check for, and the format the fix has to take.

Prompt
Context: this repository publishes an MCP server. VerifyMCP's install
scripts check failed, which means the published package declares an
install-time script (`install`, `preinstall`, or `postinstall`) that runs
automatically, with your shell's permissions, before anyone has run a
single intentional command.

Goal: the published package declares no install-time script, so the next
crawl records it as clean.

Do this:
1. This check is npm/Node-specific; confirm the package is npm before
   doing anything else.
2. Read `package.json` `scripts` for `install`, `preinstall`, and
   `postinstall` entries and work out what each one actually does.
3. Move any setup work into an explicit runtime step, or a documented CLI
   command the user runs deliberately (for example a
   `your-mcp-server init` command), instead of running it at install
   time.
4. Delete the `install`/`preinstall`/`postinstall` hooks from
   `package.json` once nothing depends on them running automatically.
5. Verify the package still installs and works with
   `npm install --ignore-scripts`; if it breaks, more logic still needs
   moving to runtime.
6. If a script is genuinely unavoidable (for example compiling a native
   addon), ask me before keeping it. If we keep it, make it as minimal as
   possible and document in the README exactly what it does and why.
7. Prepare the release, then stop and let me run the publish myself, since
   the check reads the published metadata.

Rules:
- Never run the publish command (`npm publish`, `twine upload`, `dotnet nuget
  push`, `cargo publish`, a release tag that triggers one) yourself. A
  published version is permanent and notifies every downstream consumer:
  prepare the change, show me the diff, and let me publish it.
- Never rename or obfuscate a hook to dodge detection; the fix is
  removing the behaviour, not hiding it.
- Never silently keep a script that does something other than what the
  README says it does.
- Ask me before deciding a script is "unavoidable" rather than assuming
  it.

Report back: which hooks you removed or kept, where the logic moved to,
and confirmation that `npm install --ignore-scripts` still works.

Reference: https://verifymcp.io/docs/packages/install-scripts

Written by Stuart Blackler · Last reviewed 30 June 2026.