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

trovark

v0.1.10

Published

Trust score for MCP servers, from static public signals

Readme

trovark

CI npm license node

Trust score for MCP servers. One command answers: should I adopt this server?

npx trovark github/github-mcp-server

trovark grades any MCP server 0–100 (A–F) from static, public signals only — maintenance health, spec conformance, security hygiene, and tool-surface size. It never executes the server's code. Every finding links to its evidence.

Usage

npx trovark <ref>                    # GitHub URL, owner/repo, npm, or PyPI name
npx trovark <ref> --json             # machine-readable scorecard
npx trovark <ref> --fail-under B     # CI gate: exit 1 below the threshold
GITHUB_TOKEN=... npx trovark <ref>   # higher rate limits + responsiveness signals

A bare package name that exists on both npm and PyPI is rejected as ambiguous — disambiguate with the npm:<name> or pypi:<name> prefix (e.g. npx trovark pypi:mcp-server-fetch).

About GITHUB_TOKEN

  • Scopes needed: none. trovark only calls public read endpoints (GET /repos/..., /commits, /releases, /issues, /issues/{n}/comments) against api.github.com. A classic PAT with zero scopes checked, or a fine-grained PAT with "Public Repositories (read-only)" access, is enough.
  • Without a token: everything except median issue time-to-first-response is still collected, at GitHub's unauthenticated rate limit (60 requests/hour).
  • With a token: the same signals, plus median issue time-to-first-response (Health dimension), at the authenticated rate limit (5,000 requests/hour).
  • Security note: the token is sent as a Bearer header on api.github.com requests only, and only ever used for GET reads — trovark never writes to GitHub.

CI usage

--fail-under turns a scan into a pass/fail gate: exit 0 when the grade meets the threshold, exit 1 when it doesn't, exit 2 on a resolution or network error.

The threshold is a number or a grade. A grade with a modifier gates at that label's floor (B+ = 80, A- = 85); a bare letter gates at the whole band (B = 70, the same as B-), so --fail-under B passes a B-.

The ungradeable states do not all fail the gate the same way, so a workflow that branches on the exit code needs the distinction:

| State | with --fail-under | without | |---|---|---| | INSUFFICIENT DATA | 2 | 2 | | REPO UNAVAILABLE | 2 | 2 | | LIBRARY | 1 | 0 | | DYNAMIC TOOL SURFACE | 1 | 0 |

The first two are errors either way: nothing was measured. The last two are correct, successful answers — there is genuinely no grade to give — so they only fail once a threshold demands one.

# .github/workflows/trovark.yml
name: trovark
on: [push]
jobs:
  trust-score:
    runs-on: ubuntu-latest
    steps:
      - run: npx trovark ${{ github.repository }} --fail-under B

Set GITHUB_TOKEN in the job's env for higher rate limits and issue-responsiveness signals — the default GITHUB_TOKEN GitHub Actions provides is sufficient (read-only). See About GITHUB_TOKEN for exactly which scopes it needs (none).

What the grade means

| Dimension | Weight | Question it answers | |---|---|---| | Health | 35% | Is this maintained, or one life-change from abandonment? | | Reliability | 25% | Does it target the current MCP spec? Is it tested, CI'd, pinned? | | Security | 25% | Risky tool surface, committed secrets, known CVEs in deps? | | Cost | 15% | How large is its tool surface? (tool count — the serialized token footprint is reported as a fact where measurable, but does not score) |

Missing data lowers confidence — it is never silently scored as zero. Full methodology: docs/methodology.md. Rubric is versioned; the scorecard records the version that graded it.

The observatory

The index also snapshots every scanned server's extracted tool surface on each scan and publishes changes as a neutral drift feed — the only public index that remembers what every server's tool surface looked like last month. Snapshots store hashes, not content; drift events carry zero findings and zero score impact. Details and honest scope limits: Tool-surface observatory.

Reading a scorecard

npx trovark acme/weather-mcp

trovark  ·  acme/weather-mcp
  resolved: github.com/acme/weather-mcp · graded at main@3f9c1ab
Trust Score: 74/100 (B-)   rubric v1.7.0

  health         75/100  ████████░░  high confidence
  reliability    44/100  ████░░░░░░  high confidence
  security       85/100  █████████░  medium confidence
  cost          100/100  ██████████  high confidence

Metadata Integrity: 0 findings across 2 files / 239 characters / 1 tool descriptions.
  • Trust Score: 74/100 (B-) — the overall 0–100 score and letter grade, the weighted sum of the four dimensions above. rubric v1.7.0 is the rubric version that produced this scorecard; scorecards from different rubric versions aren't directly comparable.

  • Dimension rows (health 75/100 ... high confidence) — each dimension's own 0–100 score plus a confidence level (high ≥75%, medium ≥40%, low <40% of that dimension's signals were collectible). Low confidence means the score rests on fewer inputs, not that the server scored badly.

  • Findings (printed only when a dimension surfaces one), e.g. for a server exposing a run_bash_command tool:

    [high] security/shell-exec-tool — Tool "run_bash_command" appears to execute commands or code.
           evidence: src/server.js

    security/shell-exec-tool is the finding's stable id, [high] its severity, and evidence: a file path or URL — check it yourself, trovark never asks you to take a finding on faith.

  • Metadata Integrity — a static scan of tool metadata and fetched files for hidden Unicode payloads (invisible characters that can smuggle instructions). "0 findings across N files" is a clean scan, not an unset one; a separate not checked — no files fetched line means the scan never ran because no files were retrieved.

  • Notes (printed only when relevant) — plain-language reasons a signal was missing, a dimension was excluded, or a grade was withheld.

Not every ref gets a Trust Score — trovark distinguishes "we don't know" from "there's nothing to grade":

  • Trust Score: INSUFFICIENT DATA — the grade is withheld rather than computed from partial signals. This happens when the tool surface can't be statically determined, or two or more whole dimensions have zero collectible signals; Notes explains why.
  • LIBRARY — not an MCP server — the ref is an SDK, proxy, or distribution stub with no tools of its own to grade. No score is computed, and --fail-under is a no-op against it.
  • REPO UNAVAILABLE — the reference doesn't resolve to an existing, accessible GitHub repo (renamed, deleted, or never existed). No score, no findings.
  • DYNAMIC TOOL SURFACE — the ref is a gateway, proxy or registry that assembles its tools at runtime from servers it federates, so there is no static surface to read. Grading what such a repo declares about itself would measure the wrong thing. No score is computed, and --json carries notServerReason: "dynamic".

An npm: or pypi: ref is scored at repository granularity. The package resolves to the repository that hosts it, and everything below — the tool count, every finding, every piece of evidence — describes that whole repository. For a monorepo, two different packages therefore score identically, and a finding can cite a file belonging to a sibling package. When that is the case the card says so in Notes, naming the repository and the package.

Every ref is graded at the repository's default branch, as of generatedAt. The card names the revision it read — resolved.branch, resolved.commit and resolved.treeRefSha in --json, and a graded at <branch>@<sha> segment on the terminal header — so the score can be re-derived later rather than merely re-run. For an npm: or pypi: ref this is deliberately not the published version: the package name resolves the repository, and the files are then read from that repository's default branch, which for most packages has moved past the commit the release was cut from. resolved.npmVersion records the version that would be installed, and when npm publishes a gitHead for it and that commit differs from the branch tip, the card says so in Notes. When npm publishes no gitHead, no divergence is claimed either way — the resolved: line still states exactly which branch and sha were read.

--json carries the same information as structured fields (overall, grade, dimensions[].confidence, insufficientData, notServer, unresolved) instead of prose — see src/types.ts for the full Scorecard shape.

Abridged, from a real run of npx trovark github/github-mcp-server --json:

{
  "ref": "github/github-mcp-server",
  "resolved": { "repo": { "owner": "github", "name": "github-mcp-server" },
                "branch": "main", "commit": "3f9c1ab…", "treeRefSha": "3f9c1ab…" },
  "rubricVersion": "1.7.0",
  "checksVersion": "1.0.0",
  "overall": 96,
  "grade": "A+",
  "dimensions": [
    { "id": "health",   "score": 100, "confidence": "high",   "available": 7, "total": 7, "findings": [] },
    { "id": "security", "score": 85,  "confidence": "medium", "available": 2, "total": 3, "findings": [] }
  ]
}

available and total are why each dimension reports its own confidence: a security score computed from two of three signals is a weaker claim than a health score computed from all seven, and the JSON says so rather than leaving the consumer to infer it.

What trovark is not

  • It does not run or sandbox servers (static analysis only — v1).
  • Findings are surfaces and heuristics with evidence links, not claimed exploits.

Apache-2.0.