npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

mcpaudit-guardian

v0.1.0

Published

A transparent stdio proxy that enforces security policy on MCP tool calls in real time.

Readme

mcpaudit-guardian

A transparent stdio proxy that sits between an MCP client and a real MCP server, and enforces security policy on the traffic in real time.

The problem

An MCP client injects every tool's name, description and JSON schema straight into the model's context. That makes a tool description untrusted input with system authority, and it means a server can change what it tells the model at any point after you approved it — nothing in the protocol re-checks a tool definition once a client has connected once.

MCPAudit is a companion project that audits servers offline, on a schedule, and publishes a public report. It's good at building a historical record, but by design it never touches live traffic — it can't stop a bad tool call from happening, only report on it afterwards.

mcpaudit-guardian is the other half: it actually sits in the call path. Instead of pointing your MCP client at the real server, you point it at mcpaudit-guardian, and mcpaudit-guardian spawns the real server itself and proxies everything transparently — except it inspects the tool list and every tool call as they pass through, and can block or flag what it doesn't like before the model or the real server ever sees it.

What it does

$ mcpaudit-guardian -- npx -y @modelcontextprotocol/server-filesystem /tmp
[mcpaudit-guardian] wrapping 'npx -y @modelcontextprotocol/server-filesystem /tmp' (server id: auto-3f9a2c1b8e7d)
[mcpaudit-guardian] warn: blocked tools, hidden from the model: get_weather
  • Runs every tool description through the same class of checks MCPAudit uses: prompt injection, exfiltration instructions, credential-material references, hidden content (HTML comments, zero-width and bidi Unicode), tool shadowing, overly permissive schemas, and command-execution-style capability.
  • Fingerprints every tool on every connect and compares it against a local history file, so a server that silently rewrites a tool's description gets caught the instant your client reconnects — not on someone else's nightly scan.
  • Applies a policy per finding severity: block (the tool is stripped from the list, the model never learns it exists), warn (the tool is passed through with a warning prepended to its description), or allow. Default: block critical, warn high, allow everything else.
  • Enforces the same decision on tools/call — a blocked tool's calls are refused directly by guardian and never reach the real server.
  • Logs every tool call to a local JSONL audit trail.

Install and use

No global install needed:

npx mcpaudit-guardian -- npx -y @modelcontextprotocol/server-filesystem /tmp

Wire it into an existing client config by wrapping the real command. For example, in Claude Desktop's claude_desktop_config.json:

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["mcpaudit-guardian", "--", "npx", "-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
    }
  }
}

Nothing else about the config changes. The client still talks to what looks like a normal MCP server; guardian is just standing in front of it.

Flags

mcpaudit-guardian [--server-id <id>] [--config <path>] -- <command> [args...]
  • --server-id — a stable identity for this server's history file. Recommended: without it, guardian falls back to hashing the command and args, which is fragile against incidental config changes (a different temp path, a different port) that don't actually mean "this is a different server".
  • --config — path to a policy config JSON file. Defaults to ~/.mcpaudit-guardian/config.json if present, otherwise the built-in default policy.

Policy config

{
  "bySeverity": { "critical": "block", "high": "warn", "medium": "allow" },
  "allowTools": ["some_tool_name"],
  "denyTools": ["some_other_tool"]
}

The escape hatch

A rug-pull finding on a tool that turns out to be a legitimate change (the maintainer fixed a typo, added a real parameter) shouldn't stay flagged forever:

mcpaudit-guardian approve <server-id> <tool-name>

This clears the current fingerprint for that tool so it stops being flagged, without resetting the rest of the server's history.

Try the demo

npx mcpaudit-guardian demo

Runs three scenarios against small bundled fixture servers, in a throwaway history directory: a clean tool list passing through untouched, a poisoned tool list getting filtered before the model ever sees it, and — the point of this project — the same server scanned twice with an edited tool description in between, showing the rug pull caught live on the second connect.

How it works

mcpaudit-guardian spawns the real server as a child process and proxies newline-delimited JSON-RPC 2.0 messages between your client's stdin/stdout and the child's stdin/stdout. Most traffic is written straight through as the original raw bytes — notifications, resource and prompt calls, sampling requests — unparsed and unmodified, to keep latency close to zero and avoid silently reformatting anything guardian has no reason to touch. Only three request types are ever deep-inspected: initialize (its instructions field lands in the model's context the same way a tool description does), tools/list (where policy gets applied to every tool), and tools/call (where a blocked tool gets refused directly instead of reaching the real server).

State lives under ~/.mcpaudit-guardian/: history/ holds one JSON file per server with every tool version ever seen, and audit/ holds one append-only JSONL file per server logging every tools/list decision and every tool call.

Development

npm install
npm run typecheck
npm run lint
npm test
npm run build
node dist/cli.js demo

Tests run with no network and no real npm packages — the end-to-end suite spawns a small real MCP server fixture (test/fixtures/fake-server.js) over actual stdio, not mocks.

Related project

MCPAudit — the offline complement to this project. It scans servers on a schedule and publishes a public trust registry with long-term history; this project enforces policy on live traffic in the moment. Live registry: https://rengakrishnaa.github.io/mcpaudit/.

Licence

MIT.