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

teppi-check

v0.3.0

Published

Probe any paid endpoint and print what it actually returns for the money. Reproduces any entry in the Teppi record.

Readme

teppi-check

Send one unpaid request to any paid endpoint and see what it actually advertises, and what is already broken about the listing before you pay anything.

npx teppi-check https://some-seller.example/v1/extract
npx teppi-check --mcp https://mcp.some-seller.example/mcp

No install and no dependencies: the published package is a single bundled file, so the validator that reads a schema here is the same build that read it when the record was written.

It sends the request the scheduled prober sends. Both call one handshake function, and a test runs the two side by side and fails if the bytes on the wire differ. That is what makes an entry in the record something you can check rather than something you are asked to accept.

  POST https://some-seller.example/v1/extract
  2026-08-30T10:22:14.263Z

  402 in 118ms
  endpoint answered                                   ok
  asks for payment                                    ok
  payment terms parse                                 ok
     read from the body
  offers at least one way to pay                      ok
     1 option(s)
  price is stated                                     ok
  network is stated                                   ok
  scheme is stated                                    ok
  payout address is stated                            ok
  asset is stated                                     ok
  input schema is usable                              ok
  output schema is usable                             fail
     not declared, so no response can ever be checked against it
  payment terms are not cached                        fail
     no cache-control, so a proxy may serve stale terms

  prose_in_the_url                                    defect
     a query value spells out what to put there instead of putting it

  advertised
     10000 0x2222...2222 on eip155:8453 via exact

  request  sha256:ba6f7ff0...0878
  response sha256:0a83a213...2496

  3 problems found

Why this exists

Teppi keeps the Machine Delivery Record: what happened when someone paid a machine service and waited for something back. A record is only worth reading if a stranger can check it, so the probe that produces it ships as a command anyone can run. Point it at an endpoint, compare the output to the published entry, and decide for yourself.

This is the unpaid half of the probe. It reports what an endpoint promises. Whether it delivers takes a purchase, which the full prober does on a schedule.

What it checks

| Check | Fails when | |---|---| | endpoint answered | connection refused, DNS failure, or timeout | | asks for payment | anything other than a 402 | | payment terms parse | no readable terms in the payment-required header or the body | | offers at least one way to pay | accepts is missing or empty | | price, network, scheme, payout address, asset | any entry in accepts leaves one unstated | | input schema is usable | absent, or present but not a compilable JSON Schema | | output schema is usable | same. Without one, no response can ever be validated | | payment terms are not cached | no no-store or no-cache, so a proxy may serve stale terms and stale nonces |

Terms are read from the payment-required header (base64 or plain JSON) or from the response body, because deployed servers use both.

What it finds wrong with the listing

A check reads the answer. A defect reads the listing itself, and an endpoint can answer perfectly while being impossible to buy from.

| Defect | Means | |---|---| | prose_in_the_url | a query value describes the parameter instead of filling it in, or a path segment is still :id or {id}, or an address is forty repeated characters | | path_not_found | the listed path answered 404 or 410, so there is nothing there to buy |

These are the names the public record uses, with the same sentence beside them. A test runs this rule and the one the record is built from over the same list of urls and fails if they ever give different answers, so the id you read in a Teppi entry is the id you get here.

Nothing our own bad request causes is a defect. A 400, a 422 or a 429 says something about the caller, not the seller, and none of them appear.

Remote MCP servers

--mcp runs the handshake instead: initialize, the initialized notification, then tools/list over Streamable HTTP.

| Check | Fails when | |---|---| | server answered | connection refused, timeout, or a server that never replies | | named a protocol version | it never got that far | | named itself | it never got that far | | listed its tools | it never got that far | | every tool declared an input schema | a tool an agent would have to guess the arguments for | | every tool said what it does | a tool with no description | | tool list digest | never, it prints the digest so you can compare it against a record |

A server asking for credentials or for payment is reported as such and does not fail: that is what a private or paid server is entitled to say. Only a server that did not answer fails.

The digest is a sha256 over each tool's name, description and whether it declared an input schema, sorted by name. Reordering the list does not change it and rewording a description does, which is what makes it useful for noticing that a server's instructions changed under you.

Options

  --mcp                handshake a remote mcp server instead of an x402 endpoint
  --method <verb>      tries GET then POST when not given
  --body <json|@file>  default {}
  --json               machine readable output
  --timeout <ms>       default 15000
  --user-agent <ua>    default node

Exit codes: 0 nothing to report, 1 a check failed or a defect was found, 2 the endpoint could not be reached.

Requests go over HTTPS only, apart from localhost.

Use it in CI

- run: npx teppi-check https://your-api.example/v1/thing

The command fails the build when your own endpoint stops advertising what it should, which is the failure mode nobody notices until buyers quietly stop calling.

Library

import { probe } from 'teppi-check';

const result = await probe({ url: 'https://some-seller.example/v1/extract' });
console.log(result.verdict, result.checks, result.defects);

urlHasPlaceholder(url) and defectsOf(url, httpStatus) are exported on their own, for reading a list of urls without sending anything.

MIT.