{
  "markdown": "# toolstop\n\nSmall, stateless MCP servers. Each one does a single narrow job exactly, so an\nassistant can call it instead of guessing.\n\nEvery server runs on Cloudflare Workers at `<name>.toolstop.dev`, holds no\nstate, and can also run locally over stdio.\n\n## Servers\n\n| Server | Does | Endpoint |\n|---|---|---|\n| [check-digits](packages/mcp-check-digits) | Validates check digits for IBAN, LEI, ISBN, GTIN/UPC/EAN, VIN, NPI, ISIN, ABA routing numbers and payment cards | `https://check-digits.toolstop.dev` |\n\n## Connecting\n\nRemote, over streamable HTTP. No install, no account:\n\n```json\n{\n  \"mcpServers\": {\n    \"check-digits\": {\n      \"type\": \"url\",\n      \"url\": \"https://check-digits.toolstop.dev\"\n    }\n  }\n}\n```\n\nLocal, over stdio:\n\n```bash\nnpx @toolstop/check-digits\n```\n\n## Design\n\n**Stateless.** No database, no vector index, no metered upstream API. A request\nis answered from its arguments alone. Servers scale to zero and an idle one\ncosts nothing.\n\n**Zero runtime dependencies.** No MCP SDK, no schema library. MCP over\nstreamable HTTP is request/response, which makes hand-rolled dispatch small\nenough to be worth it: faster cold starts, and no supply chain.\n\n**Telemetry records shape and outcome, never argument values.** A check-digit\nserver that logged its input would be storing real IBANs and card numbers. The\ntransport emits one row per request describing *what kind* of call happened and\nwhether it succeeded. `packages/_shared/transport.test.mjs` asserts that no raw\nargument value can reach it.\n\nThe row also carries a session id, and it is derived from the **network** the\nrequest came from, truncated to a /24 or /48 before hashing, never the full\naddress. Hashing the whole IP would not have anonymised it: the IPv4 space is 32\nbits and the other inputs are public, so the id was walkable back to one address\nuntil this was fixed on 2026-08-10. Each server's README states the complete\nrecorded row rather than only what is left out.\n\n**Every tool declares `readOnlyHint`, a complete `inputSchema` and an\n`outputSchema`**, so a client can tell what a call will do before making it and\nwhat shape comes back. The transport refuses to start a server whose tools do\nnot state their annotations, rather than defaulting them to something reassuring.\n\n## Repo layout\n\n```\npackages/_shared/     shared transport, dispatch and telemetry\npackages/mcp-<name>/  one server\nscripts/discover.mjs  derives the CI matrix from the filesystem\nscripts/smoke.mjs     protocol check against a live endpoint\n```\n\nSee [CLAUDE.md](CLAUDE.md) for the operating manual.\n\n## Development\n\n```bash\nnpm install\nnpm test                                # every server plus the shared transport\nnode scripts/smoke.mjs mcp-check-digits # protocol check against the live endpoint\n```\n\n## License\n\nMIT\n",
  "bytes": 2792,
  "sha": "cae34b48113bf0b8a17e83177a5c5b5d6b691fa2beb45cd72c71fea1dacc5e1f",
  "repo_slug": "toolstop/toolstop",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_dev_toolstop_check_digits_8543ee9a/readme"
}