# Pkg Guard Mcp

> Day-zero supply-chain checker for npm + PyPI, as a local MCP server for AI coding agents. Calls check_package before installs to surface contextual anomalies.

- **Type:** MCP server
- **Install:** `agentstack add mcp-fardenghi-pkg-guard-mcp`
- **Verified:** Pending review
- **Seller:** [fardenghi](https://agentstack.voostack.com/s/fardenghi)
- **Installs:** 0
- **Category:** [Developer Tools](https://agentstack.voostack.com/c/developer-tools)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [fardenghi](https://github.com/fardenghi)
- **Source:** https://github.com/fardenghi/pkg-guard-mcp
- **Website:** https://www.npmjs.com/package/@pkg-guard/mcp

## Install

```sh
agentstack add mcp-fardenghi-pkg-guard-mcp
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# pkg-guard

[](https://www.npmjs.com/package/@pkg-guard/mcp)
[](LICENSE)
[](https://nodejs.org)

> **`pkg-guard` is an alerting layer** — a day-zero supply-chain checker for npm + PyPI, distributed as a local MCP server for AI coding agents.
>
> `pkg-guard` runs locally via `npx`. When your AI agent (Claude Code, Cursor, Claude Desktop) is about to install a package, it calls `check_package` first and surfaces structured evidence — publish-time anomalies, lifecycle script changes, Scorecard signal, OSV advisories — so the agent (and you) can stop and look before installing.
>
> It is **not** a package-manager enforcement gate, a malware scanner, a sandbox, or a guarantee. See [Limitations](#limitations).

## What it does

Most supply-chain incidents have a small day-zero window: the malicious version lives for hours before defenses catch up. Confidence-based signals (provenance, signatures) and slow-feedback signals (CVEs, advisory databases) usually arrive too late.

`pkg-guard` looks for contextual anomalies that don't need to know the specific malware:

- **A1 — Version age:** package published moments ago
- **A2 — New lifecycle scripts / `.pth` files:** install-time code injection
- **A3 — Size delta:** unusual jump in published artifact size
- **A4 — Maintainer change:** new publisher this version
- **A5 — Author change:** new author this version
- **B1-B4 — Baseline signals:** Scorecard, OSV advisories, popularity, age

Signals combine with AND rules (not additive weights). A package with a single anomalous A-signal still gets flagged when paired with a low-popularity baseline. Returns a structured `Verdict` with `level: "ok" | "warn" | "critical"`, the signal IDs, and the sources consulted.

## What it isn't

- **Not an enforcement gate** — it surfaces evidence; your agent decides
- **Not a malware scanner** — no static or dynamic analysis of package contents
- **Not a sandbox** — packages still install with their normal permissions if you proceed
- **Not a guarantee** — heuristics can produce both false positives and false negatives; treat results as one input, not a verdict

## Install in your MCP client

`pkg-guard` is a stdio MCP server. Your AI client launches it as a subprocess. No hosted service, no OAuth, no account required.

### Step 1 — Install the package globally (recommended)

```bash
npm install -g @pkg-guard/mcp
```

> **Why global install?** MCP clients (Claude Code, Cursor, Claude Desktop) spawn the MCP subprocess without inheriting your shell's PATH. If you use `nvm` or any non-system Node install, the `npx` binary may not be on the subprocess's PATH, and the MCP connection fails with `-32000`. A global install puts `pkg-guard-mcp` on a stable path that subprocess-spawned MCP servers can find.
>
> You can use `npx -y @pkg-guard/mcp` instead if your `node` + `npx` are at predictable system paths (Homebrew Node, system Node) — see [Troubleshooting](#troubleshooting) if your client reports `-32000` or "Failed to connect."

### Step 2 — Configure your MCP client

#### Claude Code (CLI)

```bash
# After global install
claude mcp add --transport stdio pkg-guard pkg-guard-mcp

# Alternative: via npx (use absolute paths if your client reports -32000)
claude mcp add --transport stdio pkg-guard "$(which node)" "$(which npx)" -y @pkg-guard/mcp
```

#### Cursor (`.cursor/mcp.json`)

```json
{
  "mcpServers": {
    "pkg-guard": {
      "command": "pkg-guard-mcp"
    }
  }
}
```

#### Claude Desktop (`claude_desktop_config.json`)

```json
{
  "mcpServers": {
    "pkg-guard": {
      "command": "pkg-guard-mcp"
    }
  }
}
```

Restart your MCP client after editing the config. The `check_package` tool should appear in the tool list.

### Troubleshooting

| Symptom | Cause | Fix |
|---------|-------|-----|
| `-32000` / "Failed to connect" | MCP client can't find `npx` or `node` because the subprocess doesn't inherit your shell PATH (common with `nvm`) | Use the global-install path above, or pass absolute paths: ``claude mcp add --transport stdio pkg-guard `which node` `which npx` -y @pkg-guard/mcp`` |
| `sh: pkg-guard-mcp: command not found` (when calling `npx`) | Stale npx cache holding a broken older version | `rm -rf ~/.npm/_npx && npm cache clean --force` |
| Tool list missing `check_package` | Bin started but the MCP protocol handshake failed | Test directly: `echo '{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1"}},"id":1}' \| pkg-guard-mcp` should print a JSON-RPC response with `serverInfo` and `tools.listChanged: true` |

## Example

After install, drop the [adoption snippet](#adoption-snippet) below into your agent's system prompt (Claude Code's `CLAUDE.md`, Cursor rules, Claude Desktop system prompt). A typical exchange:

```
You: install left-pad

Agent: Let me check left-pad first via pkg-guard.
       [calls check_package({ ecosystem: "npm", name: "left-pad" })]
       Verdict: ok
       Signals: []
       Sources: registry, deps-dev, osv

       The package looks fine. Proceeding with `npm install left-pad`.
```

When something's wrong:

```
You: install some-suspicious-package

Agent: [calls check_package, gets level: critical]
       pkg-guard returned a CRITICAL signal:
         - A1 (version_age): published 2 hours ago
         - A2 (new_lifecycle_script): new preinstall script in v1.2.4

       I am not going to install this without explicit confirmation.
       Please review the evidence and tell me if you want to proceed.
```

## Adoption snippet

Paste this verbatim into your agent's system prompt (Claude Code's `CLAUDE.md`, Cursor rules, Claude Desktop system message, or any other MCP-capable AI coding agent). It makes the agent call `check_package` **before** any npm or PyPI install, block on `warn` / `critical` until you explicitly confirm, and ask before proceeding if pkg-guard is unavailable.

```markdown
## pkg-guard package install safety

Before installing or adding any npm or PyPI package, call the `check_package`
MCP tool from the pkg-guard server.

This applies before commands including `npm install`, `npm add`, `pnpm add`,
`yarn add`, `bun add`, `pip install`, `pipx install`, `uv pip install`,
`poetry add`, and edits to files that introduce new npm/PyPI dependencies
(`package.json`, `pyproject.toml`, `requirements.txt`, `Pipfile`).

Call `check_package` with:
- `ecosystem: "npm"` for npm/pnpm/yarn/bun packages.
- `ecosystem: "pypi"` for pip/pipx/uv/poetry packages.
- `name`: the package name.
- `version`: the exact version if known. Omit only when the install
  command would use the default/latest version.

If pkg-guard returns `level: "ok"`, proceed normally and keep the
explanation brief.

If pkg-guard returns `level: "warn"` or `level: "critical"`, do **not**
install yet. Show the user:
- `level`
- `summary_hint`
- `signal_ids`
- `signals[].evidence`
- `sources_failed`

Then ask the user for explicit confirmation before installing. Do not
infer that they want to proceed.

If the pkg-guard tool is unavailable, errors, or times out (or returns a
non-empty `sources_failed`), do **not** silently proceed. Tell the user
the supply-chain check could not be completed and ask whether they want
to proceed without pkg-guard. Do not run the install command before they
answer.

If `level: "ok"` but `sources_failed` includes `"registry"`, the
requested version probably does not exist on the registry. Treat this
as a phantom-version risk: tell the user the version was not found,
and ask before installing. (v1.0.x has a known gap where this is not
yet a first-class signal; v1.1 will add an explicit `A6:
version_not_found` heuristic.)

Do not reinterpret a `warn` or `critical` result as safe because OSV has
no advisory, because the project is popular, or because the maintainer
is well-known. The pkg-guard `level` is the authoritative alert for this
workflow.
```

> **Note:** MCP tool selection is model-controlled. The snippet strongly instructs the agent but does not enforce — a user who tells the agent to install anyway can still install anyway. `pkg-guard` is an alerting layer, not a hard gate.

## Configuration

All optional. Set as environment variables (or via your MCP client's `env` config).

| Variable | Default | What it does |
|----------|---------|--------------|
| `HMAC_LOG_SECRET` | dev-default | Per-process secret used to HMAC-hash package names in structured logs. Set to a stable random value if you want consistent hashes across `npx` invocations. |
| `PKG_GUARD_AUDIT_LOG` | `0` (off) | Set to `1` to append hash-only audit lines to `~/.pkg-guard/audit.jsonl`. Useful for analyzing your own check history; default is off so nothing touches disk. |

## How it works

For each `check_package` call, `pkg-guard`:

1. Resolves the package and version against the registry (npm or PyPI)
2. Fetches in parallel: registry metadata, [deps.dev](https://deps.dev) (Scorecard + popularity), [OSV.dev](https://osv.dev) (advisories), and for PyPI, the wheel `RECORD` file for `.pth` files
3. Runs 9 heuristics (A1-A5 acute + B1-B4 baseline)
4. Combines signals with AND rules into a `Verdict`
5. Returns: `{ level, signals[], transitive_flagged[], sources_consulted[], sources_failed[], summary_hint }`

Failed sources degrade gracefully — the call still returns a Verdict computed from whatever resolved within the timeout budget, and `sources_failed[]` tells the caller what was missing.

Privacy: structured logs and the optional audit file are **hash-only**. Package names are HMAC-SHA256'd; raw package names and versions never appear in logs or files.

## Limitations

- **Heuristic, not deterministic.** Can produce both false positives (legitimate packages with surprising release patterns) and false negatives (carefully-staged attacks that match a normal release pattern).
- **Phantom-version gap (v1.0.x).** If you query a version that doesn't exist on the registry (e.g. `react@99.0.0`), the engine currently returns `level: "ok"` with `sources_failed: ["registry"]` rather than treating "version not found" as its own signal. **Always check `sources_failed` before acting on a level: ok verdict** — if `registry` is in `sources_failed[]` for a real-world (not test) query, the version probably doesn't exist and you should not install it. Tracked for v1.1+ as a new `A6: version_not_found` heuristic.
- **English-only signal labels.** Signal descriptions are English; integrate via signal IDs (`A1`, `A2`, …) for client UIs that localize.
- **No package contents inspection.** We read metadata and (for PyPI wheels) the RECORD; we don't unpack tarballs or run dependency installers.
- **Source availability.** When deps.dev or OSV is degraded, signals that depend on them are unavailable. `sources_failed[]` reports this.
- **Stdio only in v1.0.** Hosted/multi-tenant mode (HTTP + OAuth) was scoped out for v1; see CONTRIBUTING.md if you want to help bring it back.

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md) for dev setup, test requirements, and how to add a new heuristic or MCP tool. Issues and PRs welcome.

## Security

Vulnerability reports: see [SECURITY.md](SECURITY.md). Use [GitHub Security Advisories](https://github.com/filipoardenghi/pkg-guard-mcp/security/advisories/new) for private disclosure.

## License

[MIT](LICENSE). Copyright 2026 Filipo Ardenghi.

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [fardenghi](https://github.com/fardenghi)
- **Source:** [fardenghi/pkg-guard-mcp](https://github.com/fardenghi/pkg-guard-mcp)
- **License:** MIT
- **Homepage:** https://www.npmjs.com/package/@pkg-guard/mcp

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** yes
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: flagged — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-fardenghi-pkg-guard-mcp
- Seller: https://agentstack.voostack.com/s/fardenghi
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
