Parameters
All filters, including
asset and maxPrice, must hold for one and the same payment option of a listing,
and a result shows only the payment options that satisfy them.
Price and symbol constraints fail closed: an option in an asset the instance does not know never satisfies
them. A dollar ceiling applies only to options in a US-dollar stablecoin the instance accepts (USDC,
PYUSD, USDT or USDP by symbol), and converts exactly to the asset’s base units.
Response
Constraints in the query
The query is parsed deterministically. A constraint needs an explicit trigger, such as a preposition or a clause of its own. A bare mention inside a sentence stays in the ranked text, because a wrong hard filter silently hides every right answer.- Asset and asset-denominated price constraints are recognised only for symbols of assets the instance
accepts (
TESTNET_ASSETS,PUBNET_ASSETS). A number without a currency (“up to 100 requests per second”) is not a price. - Recognised phrases are removed from the text before ranking. A query that is only constraints, such as
mcp tools on testnet, returns every matching listing: domain-verified first, then origin-verified, then the longest-listed (method: "filter"). Settlement counts play no part, since a seller could buy them. - An explicit parameter overrides the same constraint in the text, and
recognisedthen lists only what was taken from the text and applied.
Ranking
1
Filter
The candidate set is every published listing that satisfies every hard filter.
2
Lexical
BM25F over all candidates, with field weights: name 3 (service name, tool name, path words), tags 2,
description 1.5, schema 1 (parameter names and descriptions), host 0.5. The lexical ranking is never
truncated.
3
Semantic
The query and each listing are embedded locally with
all-MiniLM-L6-v2 (ONNX, CPU, pinned revision and
SHA-256 hashes). Candidates with cosine similarity at least SEARCH_SIMILARITY_FLOOR (0.3 by default) are
ranked, and the top 100 are kept.4
Fuse
Reciprocal rank fusion (k = 60) combines the two rankings. Equal scores are ordered domain-verified first,
then origin-verified, then by how long the listing has been published, then by id.
5
Group
A resource sold on several networks has one listing per network. It is returned once, at the rank of its
best-ranked listing, with every matching network’s options, like
/discovery/resources. Pages and cursors count
resources.SEARCH_EMBEDDINGS=false the service does not load the model and search is lexical-only: ranked
responses (method: "lexical") have partialResults: true, while filter-only responses do not. A search
whose query cannot be embedded, because the model fails or takes over 2 seconds, is answered the same way
rather than failing.
Each process builds its first index at startup, and /ready stays failing until it is built. After that it
checks every 5 seconds whether the catalog changed and rebuilds the index in the background. A search reads
the catalog revision at most once a second; one that arrives after a catalog change, before the background
rebuild, builds the new index itself and waits for it. An index is built from the listings and the revision
read together, so it never carries a revision without that revision’s changes.
Cursors
Cursors are opaque and HMAC-signed. Each one pins:- the request it continues: the normalised query and every filter. Reusing it with a different query or filter is refused;
- the catalog revision of the first page, so the pages of one search never skip or repeat a result when the catalog changes meanwhile;
- an expiry, 15 minutes after the page was served. The index a cursor was issued on is kept until its last cursor expires, however often the catalog changes meanwhile.
Replicas that share
SEARCH_CURSOR_SECRET accept each other’s cursors while the catalog is still at the
cursor’s revision. Without the variable, each process signs with a random key, so cursors fail after a
restart or on another replica.
Errors
Quality
Search quality is measured on a frozen, judged dataset of 500 listings and 202 queries, reproducible withpnpm eval, and gated in CI. On the test split, hybrid search reaches nDCG@10 0.742 and Recall@20 0.897
against 0.677 and 0.821 for BM25F alone, with zero filter violations; each filter is also tested on its own
with no violation and no missed listing. See
Search evaluation.