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

@nessgate/resolver

v1.22.2

Published

Open, neutral universal resolver for the agentic web: give it a domain and get one normalized answer with the machine-readable resources it publishes across ARD (well-known, rel=ard, robots Agentmap), A2A, llms.txt, API catalogs, OpenAPI, ORD, host-meta,

Readme

@nessgate/resolver

Give it a domain and your client's capabilities, and it tells you how that client can connect — and what's still missing. Dependency-free, decentralized (fetches the target domain directly, no runtime dependency on nessgate.com), and neutral (reads the standards a domain already publishes; invents no taxonomy). Runs anywhere with fetch: Node ≥18, Deno, Bun, Workers, agent runtimes.

Install

npm install @nessgate/resolver

Connect

import { plan } from "@nessgate/resolver";

const p = await plan("supabase.com", { supports: [{ protocol: "mcp", auth: ["oauth2", "none"] }] });

p.outcome;      // "ready" | "credentials-required" | "incomplete" | "broken" | "no-compatible-method"
p.connection;   // { protocol, endpoint, transport, version, auth:{ type, tokenEndpoint, scopes, … } }
                // → everything needed to connect; you supply your own credentials (never sent to anyone).
p.unmatched;    // what the service offered that your client can't use, and vice-versa

Five honest outcomes, never a guess. plan() discovers the domain, matches it against your client's declared capabilities (deterministic intersection — no scores), and resolves each protocol's real connection details from the service's own published metadata (OpenAPI servers+securitySchemes, A2A cards, the MCP OAuth chain RFC 9728 → RFC 8414). Read-only; credentials stay with you.

Want just one resource's readiness? assessReadiness(resource, { fetch }). Want the raw list of everything a domain publishes? resolve(domain) — the original resolver, below.

Self-test your own domain (CI)

npx @nessgate/resolver yourdomain.com     # bin: nessgate-ready — exit 0 = connectable

Runs the open readiness predicate client-side (nothing is sent to nessgate.com or anywhere else): discovers what your domain publishes, assesses every connectable endpoint, repeats the observation 3× (any disagreement = unstable = fail — a flaky endpoint must not pass CI), and exits non-zero with the exact missing field when your publication is incomplete or broken. Drop it in CI:

- run: npx @nessgate/resolver yourdomain.com   # fails the build until agents can connect to you

Options: --observations=N · --spacing=SECONDS (spaced observation runs) · --json. The predicate and its observation semantics are published in the NessGate repo (docs/readiness-observation-semantics.md) — anyone can re-run it and get the same verdict.

Discover (the raw list)

import { resolve } from "@nessgate/resolver";

const { resources } = await resolve("example.com");
for (const r of resources) {
  console.log(r.source, r.type, r.url); // e.g. "ard-catalog" "application/json" "https://example.com/ai-info.json"
}

It reads ARD / ai-catalog.json (well-known path, rel="ard" link, robots Agentmap:), A2A agent card, llms.txt, RFC 9727 api-catalog, ai-info.json, OpenAPI, ORD, AWP, RFC 6415 host-meta, ANP, UCP, the AID TXT record, and GB/Z 185.4 — one normalized list, each record carrying its source and native sourceUrl so you can verify against the domain directly.

Optional discovery extensions

const r = await resolve("example.com", { registry: true, delegate: true });
  • registry: true — one bounded request to the official MCP Registry for the domain's exact reverse-DNS namespace. Matching servers are added as records with evidence namespace-verified and an attribution naming the registry as the verifying party. If the registry cannot be checked, the response carries federatedUnavailable: ["mcp-registry"] instead of a silently empty result.
  • delegate: true — follows the machine-readable pointers the domain's own documents name (an llms.txt index's links; catalog entries pointing at other locations), within fixed depth/request/host/byte limits. Followed records carry evidence publisher-declared, the pointer chain in provenance, and depth; walk accounting (and any truncation) is reported in delegation.

Both options default off; output without them is unchanged. plan() accepts the same options and passes them through.

resolve(domain, opts) returns { domain, provenance, discovered, resources, checked, outcome, blockedProbes? }.

  • outcome — the single honest label: "found" (validated resources exist), "none-found" (the checks completed — clean 404s and nonexistent hosts count as answers — and no supported declaration exists at the locations checked), or "blocked" (refusals — auth walls, rate limits, timeouts, network failures — were at least as common as clean answers: the checks were prevented, so absence is unknown). blockedProbes discloses the refusal count whenever any probe was refused, even under none-found.

  • resources — the normalized union of what the domain publishes. Each record has source, sourceUrl, type (the source's own label), url, a class (how far NessGate verified it), and, where useful, name / rel / id / raw.

  • discovered — the routing map: which standards were found, and where.

  • checked — the standards probed.

Declared capabilities (verbatim, never inferred)

Where a source document itself declares operations or skills, the record carries a capabilities array copied 1:1 from the publisher's own words:

  • OpenAPI — one entry per declared operation (method, path, operationId, summary), plus a security array from the spec's own components.securitySchemes / Swagger-2 securityDefinitions. Operations are enumerated only from a complete document (one extra bounded read up to maxBytes when the spec exceeds the 64 KB detection prefix); a spec larger than the cap stays detected but not enumerated — never partially extracted.
  • A2A / GB-Z agent cards — the card's own skills (id, name, description, tags); the card-level capabilities object rides along in raw.
  • ARD entries already carry their declared media types and metadata.
  • MCP (opt-in) — pass { mcp: true } to introspect declared MCP endpoints with the protocol's own read-only handshake: initialize + tools/list only — never tools/call, no credentials (an auth wall is reported as introspection.status: "auth-required"), POSTs never follow redirects, HTTPS endpoints on the queried registrable domain only, max 3 per resolution. The server's declared tools (name, description, inputSchema) land verbatim in capabilities; introspection carries the negotiated protocol version and serverInfo; the result is labeled top-level introspected: ["mcp"].

NessGate never infers, renames, or classifies a capability. capabilities is absent when the source declares none; lists are capped at 40 and flagged capabilitiesTruncated when the publisher declares more.

Redirects and the class label

The library follows redirects and records the final URL as sourceUrl. A fetched document whose final URL crossed to a different registrable domain (e.g. a wholesale rebrand like neon.tech → neon.com) is labeled class: "verified-external-location" — never verified-publisher-location. The other classes are publisher-declared (declared in a fetched catalog, same registrable domain, target not fetched), declared-external-pointer (declared, different registrable domain, unverified), and unsupported (no usable URL). The hosted resolver at nessgate.com is domain-locked and never follows cross-domain redirects, so verified-external-location appears only in library results.

Options: { fetch, timeoutMs = 8000, maxBytes = 1_000_000, deadlineMs = 20000, org, fast, mcp, verify }. Bring your own fetch if the runtime has none.

  • verify: true — a labeled reachability pass: surfaces this resolution already fetched are reachability: "ok" with no extra request; MCP records reuse introspection results; declared pointers get one safe probe each (HEAD, then a bounded GET when HEAD is unsupported or a denial is unexplained — never a POST, never an execution), capped at 8. States: ok | auth-required | rate-limited | blocked | not-found | unreachable | unknown, plus checkedAt and evidence ({status, signal name, retryAfterSeconds} — response content is never stored). auth-required needs protocol evidence (401/407 or WWW-Authenticate); blocked means anti-bot protection was reliably identified via a small conservative signal list (NessGate identifies walls, never evades them); a bare 403 is unknown — auth systems and bot-walls both use it, and NessGate never assumes either. ok means the endpoint answered a safe request — never that operations succeed or that you are authorized.

  • deadlineMs — a global wall-clock budget for the whole resolution. Past it no new fetch starts; an empty, cut-short result is labeled outcome: "incomplete" with truncated: true — never a confident absence. A transient DNS failure on the apex is retried once before it can count as nonexistence.

  • org: true — when the exact host publishes nothing, probe a bounded set of plausible same-registrable hosts (homepage-linked developer/doc subdomains first, then docs./developers./cloud./api.) for llms.txt, ard.json and openapi.json — the library counterpart of the hosted /explore?org=1 (≤4 hosts × 3 paths). Hosts attempted are reported in orgChecked; findings classify normally.

Probed OpenAPI locations include /openapi.yaml and /openapi.yml: YAML specs are detected via the document's own top-level openapi: marker and returned as pointer records (verbatim title, no capability enumeration — the library carries no YAML parser). The llms-full.txt companion location is probed after llms.txt. One document declared through several channels (well-known + rel="ard" + robots Agentmap) yields one record, not three.

Optional GB/Z 185.5 discovery (Node only): pass opts.gbz = { gatewayUrl, fetch, query, headers } to query a gateway you configure with your own authenticated fetch (mTLS/OIDC stays on your side — the library embeds no credentials). Returned agent descriptions carry provenance: "gbz-185-5-gateway". Nothing is auto-discovered; without opts.gbz no gateway is ever contacted.

Also exported: normalizeResources, classifyResource, extractOpenApiCapabilities, normalizeDomain, validateProbeContent, probeShapeOk, parseLinkRel, parseAgentmap, parseAidRecord, isAcs, normalizeAcsGatewayResponse, and the ADAPTERS table.

In a browser

The code runs in browsers, but a browser can only fetch other domains that send CORS headers — and most .well-known files don't — so browser code resolving arbitrary domains should use the hosted endpoint instead (GET https://nessgate.com/discover/{domain}, open CORS, no auth). Resolving your own domain from your own pages works directly.

Security

This library fetches the domain you pass it and follows redirects. In Node or other server-side environments, a caller that passes an untrusted domain must validate it first: reject private, loopback, link-local, and other reserved addresses, and keep redirects on the original host. Without these checks, an untrusted input could be used to reach internal network resources (SSRF). The hosted resolver at nessgate.com performs these checks (DoH pre-check against private/reserved IPs, on-domain redirects only, size and timeout caps, HTTPS-only); when you run this library yourself, that responsibility is yours.

Specification

This is the reference client for the NessGate Resolver Specification — see the specification and the Charter. The specification is open and independently implementable.

License

Apache-2.0.