The NessGate Resolver Specification
NessGate resolves one thing:
a domain → the machine-readable resources it already publishes,
read on demand and normalized into one answer
NessGate is a neutral, format-neutral resolver. It reads whatever a domain publishes at the standard machine-discovery locations, normalizes it into one list, and links every record back to the source document it came from. It defines no format of its own, hosts nothing, and stores nothing: the resources always live on the domain's own infrastructure, under the domain's control, in whatever structure the domain chooses. NessGate reports what it read and where — never the truth, correctness, or safety of what is behind a link.
0. Scope, interoperability, and openness
NessGate is intentionally the smallest useful primitive: a resolution layer,
not a catalog, search engine, directory, or crawler. It does not describe, rank, index, or store
resources — it reads what a domain publishes and returns it normalized, with a link back to each
source. This keeps it complementary to the discovery formats and standards a domain
already uses — llms.txt, ARD / ai-catalog.json, A2A, RFC 9727 API
catalogs, OpenAPI, Open Resource Discovery, host-meta, or custom and future formats. NessGate takes
no position on the format; it only reads it. A new standard is a new adapter, never a competing
format.
The specification is open and independently implementable. The rules below are
sufficient to build a compatible resolver with no permission and no dependency on nessgate.com; the
reference implementation is open source under Apache-2.0, and the embeddable
@nessgate/resolver
library talks to target domains directly. The neutrality and free-forever commitments that make this
a shared specification rather than one vendor's service are set out in the
NessGate Charter.
1. Resolution
GET https://nessgate.com/discover/{domain}
| Field | Type | Meaning |
|---|---|---|
domain | string | The normalized domain that was queried. |
provenance | string | Always "self-published": the resources were read from the domain itself, not asserted by NessGate. |
discovered | array | The routing map — one {"type", "url"} per standard the domain publishes, and where. |
resources | array | The normalized union of what those documents contain (see §2), flattened into one list, capped for safety. |
checked | array | The full list of standards NessGate probed for, so a client knows what was looked at even when nothing was found. |
note | string | Human-readable reminder that these are self-published locations, reported as-is, verifiable via each sourceUrl. |
Status codes: 200 (a successful observation — discovered
may be empty) · 400 invalid domain · 429 rate limited.
Normalization: input is lowercased; scheme, path, query, port, trailing dots, and
a leading www. are stripped. Internationalized domains use their ASCII/punycode form.
Answers are computed fresh and cached at the edge for 10 minutes; no domain data or answer content
is stored beyond that cache (the only other state is anonymous, categorical outcome events — see the
Charter).
2. The normalized resource record
Each entry in resources is a thin, uniform record. NessGate reuses each source's own
labels and never invents a taxonomy of its own:
| Field | Meaning |
|---|---|
source | Which standard this record came from (e.g. ard-catalog, api-catalog, host-meta). |
sourceUrl | The native document the record was read from. Always authoritative — follow it to verify the record against the domain itself. |
type | An open label, taken from the source where possible (an ARD media type, a link rel, an AWP protocol key). Clients must not assume a closed set. |
url | The resource URL. |
name, id, rel, raw | Optional — a display name, the source identifier, a link relation, or the original record — included where the source provides them. |
NessGate imposes no schema beyond what is needed to merge these sources. A malformed source document is simply skipped; it can never break resolution.
3. Sources read
The resolver reads what a domain publishes through an adapter architecture. Each adapter is a small, independent reader for one standard, and every adapter uses one of four discovery channels to find its document:
- well-known — GET a fixed path (or paths) on the domain.
- link-rel — parse a
<link rel="ard">(orrel="ai-catalog") in the domain's homepage, then GET the target. - robots — parse an
Agentmap:directive in/robots.txt, then GET the target. - dns — a DNS-over-HTTPS TXT lookup at a well-known node.
Each adapter is READ, never defined by NessGate; adding support for a new standard is a new adapter here, never a change to any domain. The active adapters:
| Adapter | Channel | Location |
|---|---|---|
llms.txt | well-known | /llms.txt |
ard-catalog — Agentic Resource Discovery | well-known | /.well-known/ard.json, /.well-known/ai-catalog.json |
a2a-agent-card — A2A | well-known | /.well-known/agent-card.json, /.well-known/agent.json |
api-catalog — RFC 9727 | well-known | /.well-known/api-catalog |
ai-info.json — informal convention | well-known | /ai-info.json |
openapi | well-known | /openapi.json |
ord — Open Resource Discovery | well-known | /.well-known/open-resource-discovery |
awp — AWP manifest (provisional) | well-known | /.well-known/awp.json |
host-meta — RFC 6415 | well-known | /.well-known/host-meta.json |
anp — Agent Network Protocol (emerging) | well-known | /.well-known/agent-descriptions (JSON-LD CollectionPage) |
ucp — Universal Commerce Protocol (emerging; Google + Shopify) | well-known | /.well-known/ucp, /.well-known/ucp/manifest.json |
ard-link — additional ARD surface | link-rel | <link rel="ard"> in the homepage |
ard-agentmap — additional ARD surface | robots | Agentmap: directive in /robots.txt |
aid — AID (draft) | dns | TXT record at _agent.<domain>: v=aid1;u=<uri>;p=<proto>;a=<auth> |
NessGate implements ARD's normative domain resolution — it fetches
/.well-known/ard.json (ard-catalog) and honours the
<link rel="ard"> relation (ard-link), both MUST in
ARD v0.91 §5.1 — plus the robots.txt Agentmap: surface (ard-agentmap).
ARD's optional in-page JSON-LD is found only by general web crawling, which NessGate does not do; its
DNS mechanism is described in §5.1 but not yet normatively specified (no record type or parameters).
Neither is implemented — a guessed record would be fake conformance.
anp and ucp are emerging; aid and awp are
drafts. Publishing one is not a guarantee of anything on its own — NessGate reads whatever is there
and reports it as-is. Note: the aid adapter is the AID TXT mechanism
(v=aid1 at _agent); it is not the IETF DNS-AID draft, which uses
SVCB records at _agents.<domain> and is a separate, unimplemented mechanism.
GB/Z 185 (China, 智能体互联) — 185.4 normalized, 185.5 gated. NessGate normalizes
GB/Z 185.4 agent descriptions ("ACS") — an A2A-family card with GB/Z extensions (an agent identity
code, an mTLS scheme, a certificate block) — recognized by content and labelled
gbz-185-4, preserving those fields and provenance. Recognition is domain-first: an ACS
served at the agent-description location NessGate already reads is normalized; no GB/Z-specific path
is guessed. GB/Z 185.5 discovery is a federated gateway service with no domain-native location, so
it is not part of this hosted resolver and is never auto-discovered; the embeddable library exposes
it only as an opt-in, Node-only call against a caller-configured gateway with a caller-supplied
authenticated fetch. No guessed endpoints, no fake conformance.
For each adapter, the first candidate location returning valid content wins. Fetches are HTTPS
only, size- and redirect-capped, on-domain, and identify as NessGate-Discover/1.0.
4. What NessGate does not do
- No storage. Each answer is computed on request and dies with its 10-minute edge cache. There is no registry, no database of domains, and no record of who queried what.
- No crawling or indexing. NessGate fetches only the specific well-known paths above, only for the domain in the request, only when asked.
- No trust or safety claim.
provenanceisself-published: NessGate reports what a domain serves and links back to it. Whether a resource is correct, safe, or truly the owner's is for the client to judge from thesourceUrl. - No ranking. Results are returned in discovery order. There is nothing to buy.
5. Stability and versioning
The specification version (this document) is versioned separately from the reference-software version. Within a major specification version:
- The
/discover/{domain}response shape — the fields in §1 and the record shape in §2 — is stable. Changes are additive only: new optional fields may appear, and clients must ignore fields they do not recognize. - The set of
typelabels is open by design and will never become a closed enum. - The list of sources read (§3) may grow — that is additive and expected.
- A field-by-field reference for the shared response shapes — the
evidence/class/readiness/connect vocabularies, provenance forms, and every disclosure field — is maintained atdocs/data-model.md. - If a breaking change is ever unavoidable, it will live under a new path (e.g.
/v2/…) with the v1 endpoint maintained, announced in the changelog.
6. Machine endpoints
/discover/{domain} | The resolver — exact-host, strict, deterministic (CORS open, no auth). Stable contract (§5). |
/explore/{domain} | Evidence-based resolver (additive, evolving): /discover plus bounded delegated discovery of publisher-declared pointers and attributed MCP-Registry federation; with ?org=1, Organization Discovery probes a bounded set of plausible same-registrable-domain hosts and reports only verified resources; with ?related=1, Related Discovery returns a separate related[] layer (publisher-declared-related / registry-verified-related / infrastructure-correlated-candidate — corroborating signals never promote). Each record carries an evidence class (publisher-hosted/publisher-declared/namespace-verified/candidate/same-domain-host) and a provenance chain. Strictly bounded, stateless; no crawling, no AI, no ownership claim. |
/explore/{domain}?readiness=1 | Connection readiness (opt-in, additive): each connectable resource gains a readiness block — ready / credentials-required / incomplete / broken, with missing[] naming the exact under-published field — assessed read-only from the service's own metadata (OpenAPI servers+securitySchemes, A2A cards, the MCP OAuth chain RFC 9728 → 8414). No scores; credentials stay with the caller. |
POST /connect/{domain} | Connection plan: the caller's declared client capabilities are matched against what the domain publishes (deterministic intersection) and one outcome is returned — ready / credentials-required / incomplete / broken / no-compatible-method — with a concrete plan (protocol, endpoint, transport, version, auth metadata) and provenance. Client capabilities are input only; nothing is stored. |
/mcp | Model Context Protocol server (Streamable HTTP, no auth) exposing three read-only tools — discover_domain, connect_domain, check_readiness — so AI agents can call the resolver natively. |
resolver.mjs · @nessgate/resolver | The embeddable, dependency-free resolver library — same normalization, run in your own process, no dependency on nessgate.com. |
/openapi.json | OpenAPI 3.0 description of this API. |
/llms.txt | Guidance for AI agents. |
/sitemap.xml, /robots.txt | Crawler discovery. |
/.well-known/security.txt | Security contact (RFC 9116). |
/.well-known/api-catalog | NessGate's own RFC 9727 API catalog, dogfooding a standard it reads. |