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

@m9ter1a/mcpcheck

v0.1.1

Published

Audit any MCP server for agent ergonomics: get a 0-100 score and a list of what breaks for the agent.

Downloads

34

Readme

mcpcheck

npx @m9ter1a/mcpcheck ./server.js

./server.js is a placeholder — replace it with the path, command, or URL of a real MCP server. Point it at nothing and you'll get F / 0, because there was no server to connect to. New here? Run npx @m9ter1a/mcpcheck --help first.

Audit any MCP server for agent ergonomics — one command, a 0–100 score, and a list of what breaks for the agent.

Installed globally (npm i -g @m9ter1a/mcpcheck), the command is simply mcpcheck. The examples below use that short form.

  mcpcheck  ./server.js
  good-weather v1.0.0  ·  stdio

  Grade A   100/100   2 tools

  Protocol  ██████████ 100
  Schema    ██████████ 100
  Context   ██████████ 100
  Probes    ██████████ 100

  0 errors  ·  0 warnings  ·  0 info
  No issues found. This server is agent-friendly.

  MCP Score: A (100)

Why

The MCP Inspector is a manual GUI for poking at a server by hand. mcpcheck is the opposite: a non-interactive audit you can run in CI and get a grade from.

And it grades the thing that actually hurts an agent — not spec conformance (the SDKs already handle that), but ergonomics:

  • bloated tool descriptions burn context on every single request
  • 40+ tools wreck tool-selection accuracy
  • a 20k-token tool response can blow up a whole session
  • logs on stdout silently corrupt the stdio transport

mcpcheck connects as a real MCP client (stdio or streamable HTTP), introspects the server, runs static and dynamic checks, and prints a scored report.

Usage

mcpcheck --help                       # list every command and flag
mcpcheck ./server.js                  # spawn `node ./server.js` over stdio
mcpcheck "python server.py --stdio"   # any command
mcpcheck -- python server.py --stdio  # explicit command passthrough
mcpcheck https://example.com/mcp      # streamable HTTP

mcpcheck ./server.js --json           # machine-readable report
mcpcheck ./server.js --markdown       # Markdown + badge, for CI comments
mcpcheck ./server.js --min-score 80   # exit non-zero below a threshold
mcpcheck ./server.js --no-probes      # static analysis only
mcpcheck ./server.js --allow-write    # also probe non-readOnly tools (see below)

Exit code is non-zero when the server fails to connect, has any error-level finding, or scores below --min-score — so it works as a CI gate out of the box.

What it checks

A · Protocol & handshake

  • initialize handshake completes
  • capabilities match reality (declares tools but tools/list is empty/broken)
  • unknown methods return a JSON-RPC error instead of crashing
  • non-JSON output on stdout — the classic transport-corrupting bug

B · Schema hygiene

  • missing tool / parameter descriptions
  • invalid inputSchema (not type: object, no required)
  • names: duplicates, unsafe characters, mixed snake_case/kebab-case conventions (either style is fine — just be consistent)
  • missing safety annotations (readOnlyHint, destructiveHint) on mutating tools
  • missing outputSchema

C · Context budget (the differentiator)

  • total token cost of tools/list (flagged past ~5k)
  • descriptions that are too terse or bloated
  • too many tools (selection degrades past ~40)
  • near-duplicate tools, clustered via character-trigram similarity — no embeddings, no API keys

D · Dynamic probes

  • calls tools with empty / invalid arguments and checks for a structured error rather than a crash
  • response size in tokens (missing pagination)
  • per-call latency
  • secret / absolute-path leaks in tool output

Probes are safe by default: only tools that explicitly declare readOnlyHint: true are called. Use --allow-write to probe everything.

Scoring

Each category is scored 0–100 (errors cost the most, then warnings, then info). The overall score is a weighted average mapped to a letter grade (A ≥ 90, B ≥ 80, C ≥ 70, D ≥ 60, F otherwise). Categories that don't apply to a server (e.g. no tools) are dropped and the weights renormalised.

By default the score includes the dynamic Probes category. Running with --no-probes drops it and scores on static analysis only, so the number will differ — expect the two modes to disagree on the same server.

Badge

Every run prints a badge snippet for your README:

MCP Score: A (94)

CI

# .github/workflows/mcpcheck.yml
name: mcpcheck
on: [push, pull_request]
jobs:
  audit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 20 }
      - run: npm ci && npm run build   # build your server first
      - run: npx @m9ter1a/mcpcheck ./dist/server.js --min-score 80

Development

npm install
npm run build      # compile to dist/
npm test           # build + vitest (unit rules, scoring, stdio & HTTP e2e)
npm run bench      # score a set of popular MCP servers (writes bench/RESULTS.md)

CI runs the test suite on Linux, macOS, and Windows (Node 20 & 22) via .github/workflows/ci.yml.

Security & privacy

  • Runs locally, phones nobody. mcpcheck makes no network calls except to the MCP server you point it at. No telemetry, no analytics — none of your (or your server's) data is sent anywhere else.
  • Its output can quote server responses. The probe checks call read-only tools and may surface snippets of what a server returns, including any secrets it flags as leaking. Treat --json / --markdown output as potentially sensitive and review it before pasting into public CI logs or pull requests.
  • Probes are read-only by default. Only tools marked readOnlyHint: true are called unless you pass --allow-write. Auditing a server also means running its code, so only point mcpcheck at servers you trust.

Notes & limitations

  • Token counts are estimates (~4 chars/token). They are meant to flag budget problems, not to bill you — and mcpcheck stays zero-config and zero-API-key as a result.
  • mcpcheck reads tools/list more leniently than the official client on purpose: a single malformed tool won't blind the audit to the rest of the server.
  • Built against MCP TypeScript SDK 1.29 / protocol negotiated by that SDK. MCP moves fast; the supported version is pinned in package.json.

License

MIT