Endpoints: 28,729MCP servers: 18,414Payout addresses: 2,071Paid calls: 1,568Letters: 14Defects: 1,338counted 1 min ago
teppi

Server definition

Hash
sha256:8e526cd4d8c231472f0fb5c7d63442ffc18ba4c8fa4e4f283ce4db94c73dd945
What it is
What a remote MCP server returned when asked what it offers: 8 tools

The blob, as servednamed by its sha256

{ "instructions": "You are using the AirShelf Catalog — a cross-vendor, datasheet-grounded B2B product catalog. It is for developers embedding shopping research into their applications; merchants supply the catalog rather than call these tools. Act as a consultative product advisor, not a search box.\n\nTERMS\n- A golden record is AirShelf's verified product record, and provenance identifies which page each fact came from.\n- Verified means matched to an AirShelf catalog record. Live-unverified means confirmed on a live page during this run but not yet in the catalog; MPN-confirmed means that live page matched the manufacturer part number.\n- The market parameter biases discovery and marketplace checks toward seller pages serving that country. \"Available in <market>\" means the seller page serves that market, not that stock is guaranteed.\n\nWORKFLOW\n1. Understand the need. If the request lacks a use case, ask ONE focused qualifying question, paired with a useful insight (\"these run 50k labels/day — is that your volume?\"). Stop as soon as you can recommend; never ask more than ~3 questions. If the message already has a use case + any of (budget, volume, environment, timeline), skip qualifying and recommend immediately.\n2. Recommend from real data. Search the catalog before answering a product question — it is CROSS-VENDOR, so find the best fit across brands rather than pre-filtering to one. Use the get/compare/equivalents tools to support the pick. In 1–2 sentences, say WHY it fits the buyer's stated need.\n3. Quote only on a real buying signal — after you have recommended a product AND the buyer explicitly wants to proceed (\"get a quote\", \"pricing\", \"talk to sales\"). Pass the buyer's own name and work email, and include the context you already gathered rather than re-asking. Resolve the merchant first where the server exposes a merchant list. A quote request is confirmed by the buyer from their own inbox before the merchant sees it, so tell them to expect that email.\n\nGROUNDING\n- Only state specs that appear in tool results. Do not assert a spec that is not present in the product's golden record — a field it does not list is \"not confirmed\", never an inference, and spec_absence_note names those fields. If unsure about a capability, say so and suggest confirming with the merchant.\n- Search the catalog before handing a product question to a human. The catalog is grounded and usually has the answer, so a handoff without a search is rarely the right move; when the response says weak_match or no_match, say what could not be matched instead of substituting a product that violates the constraint.\n- Present each product on its own merit. Do not repeat or validate a competitor's specs the buyer quotes, and avoid superlatives (\"best\", \"leading\", \"outperforms\") — let the buyer compare.\n- Do not invent pricing, contract terms, or commitments — a quote hands those to the merchant's sales team.\n- Live-lookup results (tier3 blocks, find_products candidates) are single-source and unverified. Cite their source_url with any fact taken from them, and keep them separate from verified catalog rows.\n- NEVER put a capability on a named machine that its record does not state. Measured 2026-08-21 against 26 shopper questions; these are the four shapes it actually takes, in order of frequency, and all four are forbidden:\n (a) CLASS GENERALIZATION — \"all-in-ones usually include an ADF\", \"printers like this handle thousands of pages a month\". Usually true, still a fabrication once attached to a specific model.\n (b) UNPACKING A COMPOUND TERM — the record says \"all-in-one\"; the answer says \"combines printing, scanning and copying\". You have turned one stated word into three unstated capabilities. Repeat the vendor's term; do not enumerate what you think it contains.\n (c) DERIVED NUMBERS — \"roughly 60 labels per minute\" computed from a print speed, \"3,000 pages a month\" inferred from a duty cycle. A number you calculated is not a number the vendor published. State the figure the record gives, in the unit it gives it.\n (d) BENEFIT AND OUTCOME CLAIMS — \"eliminates cartridge costs\", \"satisfies your return-label requirement\", \"cost-effective for your volume\". These read as helpfulness and assert product behaviour nobody documented.\n (e) INFERRING ONE CAPABILITY FROM ANOTHER — \"it is wireless, so it still prints when the internet is down\", \"it has an ADF, so it does duplex scanning\". Two specs that usually travel together are still two specs; the record either states the second one or it does not.\n (f) NEGATIVE CAPABILITY CLAIMS — \"it cannot print on plain paper\", \"it does not support Chromebooks\". Saying what a machine CANNOT do is as much a claim as saying what it can, and steering a buyer away on an unstated limitation is the same defect pointed the other way. The honest form is \"the record does not show plain-paper support\", never \"it cannot\".\n A HEDGE DOES NOT LICENSE ANY OF THEM: \"typically has duplex, though the record does not confirm it\" still put duplex on the machine. Name the missing field and stop. This applies to EVERY product you name, including one mentioned in a single clause in passing.\n- If the request is not about sourcing products, say so briefly and redirect to what the catalog covers.\n\nANSWERING WELL\n- When the buyer asks for several options, give at least two; when one candidate uniquely satisfies a constraint they named, pick that one rather than averaging across the two you happened to compare.\n- Accessories (keycap sets, toner cartridges, ribbon rolls, sample packs, cables) are not answers to a \"which product should I buy\" question, even when they rank highly.\n- Treat form factor as a hard constraint: \"A4-only fleet policy\" or \"desktop\" rules out an A3 floor-standing device.\n- On comparisons, state each must-have fact before the recommendation (\"K5X is 87 keys, $109; K3X is 84 keys, $89; both hot-swap + wired\") rather than jumping to the pick.", "tools": [ { "description": "Compare 2-10 catalog products side-by-side on their datasheet specs. Slugs come from search_catalog and are case-insensitive and dash-tolerant (\"e-STUDIO 331AC\", \"toshiba-e-studio-331ac\" and \"e-studio331ac\" all resolve to the same product).\n\nReturns one item per product with canonical_name and spec_absence_note (spec fields absent from that product's golden record, AirShelf's verified product record). Branch on each item's commercial_data.actionable before using price or stock; stale observations are withheld from action fields. A slug that does not resolve comes back as not_found with a did_you_mean suggestion. The `provenance` option adds the source page and source type already stored with each fact.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "provenance": { "description": "Include the stored source page and source type for each fact", "type": "boolean" }, "slugs": { "description": "Catalog slugs to compare", "items": { "minLength": 1, "type": "string" }, "maxItems": 10, "minItems": 2, "type": "array" } }, "required": [ "slugs" ], "type": "object" }, "name": "compare_products", "outputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "count": { "type": "number" }, "items": { "items": { "additionalProperties": {}, "properties": { "canonical_name": { "type": "string" }, "manufacturer": { "type": "string" }, "modelName": { "type": "string" }, "price": { "anyOf": [ { "type": "number" }, { "type": "null" } ] }, "slug": { "type": "string" }, "spec_absence_note": { "anyOf": [ { "type": "string" }, { "type": "null" } ] } }, "required": [ "slug" ], "type": "object" }, "type": "array" } }, "required": [ "items" ], "type": "object" } }, { "description": "Explain the evidence behind a catalog row. Returns stored processing stages when available and always returns a golden-record field summary with source coverage. A field's evidence_sha256 is the SHA-256 of the source document AirShelf archived when it extracted that claim. A caller holding the same bytes can compare the hash to check that the cited document has not changed. AirShelf does not serve those archived bytes, and the hash does not promise they remain retrievable. record.scraped_at is the catalog row's scrape time, not a per-claim evidence capture time.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "slug": { "description": "Composite slug to explain", "minLength": 1, "type": "string" } }, "required": [ "slug" ], "type": "object" }, "name": "explain_product", "outputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "canonical_name": { "type": "string" }, "category": { "type": "string" }, "count": { "type": "number" }, "note": { "type": "string" }, "record": {}, "sku": { "type": "string" }, "slug": { "type": "string" }, "trace": {}, "trace_status": { "enum": [ "available", "not_recorded" ], "type": "string" } }, "type": "object" } }, { "description": "Discover candidate products for a buyer need. Takes a need in natural language (e.g. \"best value home espresso machine\", market \"TH\"), checks the verified catalog first, then uses live web discovery only when the catalog has no candidates. Returns up to 3 candidates with explicit fit accounting.\n\nfind_products is the quick candidate-list tool; research_shopping is the full verified-research job. For a specific brand+model, search_catalog is cheaper and returns the same live-lookup block on a miss.\n\nResponse fields:\n• candidates[].verification — \"catalog-candidate\" for a catalog starting point whose fit still needs checking, or \"live-unverified\" for a live page read during this run.\n• candidates[].status — \"resolved\" means both identity and the parsed buyer constraints were supported by the cited page; \"abstain\" means identity or need fit could not be established. Inspect constraint_check for matched, conflicting, and unverified requirements.\n• candidates[].constraint_check.receipts maps each receipt-backed matched requirement to its supporting source URL and trust label.\n• Candidates come from current web-search results, so they are a sample of what the market offers rather than a ranking.\n• status at the top level — \"no_match\" means discovery ran but no candidate was confirmed as satisfying the need; \"disabled\", \"rate_limited\", or \"unavailable\" means no discovery ran.\n\n• live_discovery.status=\"unavailable\" means receipted catalog candidates were returned while live discovery was unavailable.\n\nOptional `market` (ISO 3166-1 alpha-2) biases discovery and marketplace checks toward seller pages serving that country and scopes the lookup cache. \"Available in <market>\" means the seller page serves that market, not that stock is guaranteed.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "market": { "description": "Buyer market as ISO 3166-1 alpha-2 country code (e.g. \"TH\"). Biases discovery and marketplace checks toward seller pages serving that country and scopes the cache; availability is not a stock guarantee.", "type": "string" }, "max": { "default": 3, "description": "Max candidates to verify (each costs a live lookup; capped at 3).", "maximum": 3, "minimum": 1, "type": "integer" }, "need": { "description": "The buyer need in natural language, e.g. \"quiet mechanical keyboard for open office\" or \"best value home espresso machine\".", "maxLength": 200, "minLength": 3, "type": "string" } }, "required": [ "need" ], "type": "object" }, "name": "find_products", "outputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "candidates": { "items": { "additionalProperties": {}, "properties": { "cached": { "type": "boolean" }, "guidance": { "type": "string" }, "identity": { "additionalProperties": false, "properties": { "brand": { "type": "string" }, "model": { "type": "string" } }, "required": [ "brand", "model" ], "type": "object" }, "mpn_confirmed": { "type": "boolean" }, "product": { "additionalProperties": {}, "propertyNames": { "type": "string" }, "type": "object" }, "query": { "type": "string" }, "reason": { "type": "string" }, "source_tier": { "type": "string" }, "source_url": { "type": "string" }, "status": { "enum": [ "resolved", "abstain", "declined" ], "type": "string" }, "tier": { "type": "number" }, "verification": { "type": "string" } }, "required": [ "query", "tier", "status" ], "type": "object" }, "type": "array" }, "error": { "type": "string" }, "guidance": { "type": "string" }, "live_discovery": { "additionalProperties": false, "properties": { "guidance": { "type": "string" }, "reason": { "type": "string" }, "status": { "const": "unavailable", "type": "string" } }, "required": [ "status" ], "type": "object" }, "market": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "need": { "type": "string" }, "reason": { "type": "string" }, "serp_considered": { "type": "number" }, "status": { "enum": [ "ok", "no_match", "disabled", "rate_limited", "unavailable", "error", "refused" ], "type": "string" }, "took_ms": { "type": "number" }, "verification": { "type": "string" } }, "required": [ "candidates" ], "type": "object" } }, { "description": "Get the full golden record (AirShelf's verified product record) and latest price for one catalog product by slug (\"<manufacturer>-<model>\").\n\nReturns the product's specs and provenance (which page each fact came from), plus canonical_name (its exact catalog name). A field's evidence_sha256 is the SHA-256 of the source document AirShelf archived when it extracted that claim. A caller holding the same bytes can compare the hash to check that the cited document has not changed. AirShelf does not serve those archived bytes, and the hash does not promise they remain retrievable. Branch on commercial_data.actionable before using price or stock: observations older than 24 hours are withheld from latestPrice and retained only as labelled last_observed history. For quote-gated B2B pricing, a null price with a quote path is expected rather than an error. In clients that render MCP Apps the response also draws one product card per call. related_products — relationships extracted from vendor documents (e.g. compatible toner or drum accessories with their source quotes, functional equivalents, supersessions); each entry names the related catalog slug, the relation type, its direction (direction is \"from_this\" when the relation reads this-product → related-product, \"to_this\" when it reads related-product → this-product), and the source URL and quote the relation was extracted from.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "slug": { "description": "Composite slug, e.g. toshiba-b-ex4t1-ts12-qm-r", "minLength": 1, "type": "string" } }, "required": [ "slug" ], "type": "object" }, "name": "get_product", "outputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "action": { "enum": [ "quote", "link" ], "type": "string" }, "benefits": { "items": { "type": "string" }, "type": "array" }, "buttonLabel": { "type": "string" }, "buyUrl": { "type": "string" }, "imageUrl": { "type": "string" }, "pricing_gated": { "type": "boolean" }, "product": { "additionalProperties": {}, "properties": { "cited_field_count": { "description": "Number of golden-record fields with claim-level citations.", "type": "number" }, "field_count": { "description": "Total golden-record fields used as the evidence coverage denominator.", "type": "number" }, "latestPrice": { "anyOf": [ { "additionalProperties": {}, "properties": { "capturedAt": { "type": "string" }, "currency": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "inStock": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ] }, "price": { "type": "number" }, "retailer": { "anyOf": [ { "type": "string" }, { "type": "null" } ] } }, "required": [ "price", "currency", "retailer", "inStock", "capturedAt" ], "type": "object" }, { "type": "null" } ], "description": "Latest valid price observation within 24 hours. Null when absent or stale; stale history remains in commercial_data.last_observed." }, "lifecycle_status": { "description": "Retirement marker from stored product evidence. current means no retirement marker was found.", "enum": [ "current", "retired" ], "type": "string" }, "pdfFilenames": { "description": "Stored source PDF filenames. A filename is not a download URL.", "items": { "type": "string" }, "type": "array" }, "qualityScore": { "description": "Percentage of golden-record fields with claim-level citations. Zero when there are no fields.", "type": "number" }, "related_products": { "description": "Documented related catalog products, including accessories, equivalents and replacements.", "items": { "additionalProperties": {}, "properties": { "direction": { "description": "from_this means this product points to the related product; to_this means the reverse.", "enum": [ "from_this", "to_this" ], "type": "string" }, "relation": { "description": "Relationship type recorded from vendor documents.", "type": "string" }, "slug": { "type": "string" }, "source": { "anyOf": [ { "additionalProperties": {}, "propertyNames": { "type": "string" }, "type": "object" }, { "type": "null" } ], "description": "Stored source URL, quote, section or page for the relationship; null when none was recorded." } }, "required": [ "slug", "relation", "direction" ], "type": "object" }, "type": "array" }, "sources": { "anyOf": [ { "anyOf": [ { "items": { "anyOf": [ { "additionalProperties": {}, "properties": { "type": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Stored source type, such as pdf or product_page." }, "url": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Source document or product-page URL when recorded." } }, "type": "object" }, { "type": "string" } ] }, "type": "array" }, { "additionalProperties": {}, "propertyNames": { "type": "string" }, "type": "object" } ] }, { "type": "null" } ], "description": "Stored evidence sources. Imports may preserve a source object, use ref instead of url, or list plain strings. Null when unavailable." }, "updatedAt": { "description": "Catalog row update time as an ISO 8601 timestamp, not a per-claim verification time.", "type": "string" } }, "type": "object" }, "productId": { "type": "string" }, "related_products": { "description": "Documented related catalog products, including accessories, equivalents and replacements.", "items": { "additionalProperties": {}, "properties": { "direction": { "description": "from_this means this product points to the related product; to_this means the reverse.", "enum": [ "from_this", "to_this" ], "type": "string" }, "relation": { "description": "Relationship type recorded from vendor documents.", "type": "string" }, "slug": { "type": "string" }, "source": { "anyOf": [ { "additionalProperties": {}, "propertyNames": { "type": "string" }, "type": "object" }, { "type": "null" } ], "description": "Stored source URL, quote, section or page for the relationship; null when none was recorded." } }, "required": [ "slug", "relation", "direction" ], "type": "object" }, "type": "array" }, "title": { "type": "string" } }, "required": [ "title", "productId", "buttonLabel", "action" ], "type": "object" } }, { "description": "List public AirShelf merchants that have an assigned slug and at least one active product. Internal/demo and empty catalogs are excluded. Returns each merchant's name, slug, and product count; the slug is the `merchant` argument for request_quote.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": {}, "type": "object" }, "name": "list_merchants", "outputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "merchants": { "items": { "additionalProperties": {}, "properties": { "checkout_capability": { "description": "shopify indicates a connected Shopify store; redirect sends the buyer to the product page.", "enum": [ "shopify", "redirect" ], "type": "string" }, "domain": { "type": "string" }, "manifest_url": { "description": "Merchant agent manifest URL with supported endpoints and capabilities.", "type": "string" }, "name": { "type": "string" }, "product_count": { "exclusiveMinimum": 0, "type": "number" }, "products_url": { "description": "Merchant product-listing endpoint URL.", "type": "string" }, "search_url": { "description": "Merchant-scoped product-search endpoint URL.", "type": "string" }, "slug": { "type": "string" } }, "required": [ "name", "slug", "product_count" ], "type": "object" }, "type": "array" }, "total": { "type": "number" } }, "required": [ "merchants" ], "type": "object" } }, { "description": "Send a quote request for catalog products to a merchant's sales team on behalf of a named buyer.\n\nThis is a two-step, double opt-in flow. The first call emails a confirmation link to `contact.email` and returns status \"confirmation_required\"; no lead exists and no merchant is contacted until the buyer confirms. A later call with the same arguments reports \"awaiting_confirmation\" while the email is unconfirmed, or \"received\" with a reference_number after confirmation.\n\nMerchant slugs come from list_merchants. Network-catalog brands that are absent from that list use merchant:\"airshelf-network\" with brandSlug:\"<manufacturer-slug>\"; AirShelf routes the confirmed request to that brand.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "brandSlug": { "description": "Manufacturer slug (from search results) — required with merchant:\"airshelf-network\" so the lead reaches the right brand", "minLength": 1, "type": "string" }, "contact": { "description": "Buyer contact details", "properties": { "company": { "description": "Buyer company", "type": "string" }, "email": { "description": "Buyer work email", "format": "email", "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", "type": "string" }, "name": { "description": "Buyer name", "type": "string" } }, "required": [ "name", "email" ], "type": "object" }, "merchant": { "description": "Merchant slug or id (from list_merchants), or \"airshelf-network\" for network-catalog brands", "minLength": 1, "type": "string" }, "notes": { "description": "Any extra context from the buyer", "type": "string" }, "products": { "description": "Catalog slugs the buyer is interested in", "items": { "minLength": 1, "type": "string" }, "maxItems": 50, "minItems": 1, "type": "array" }, "quantity": { "description": "Units the buyer wants", "exclusiveMinimum": 0, "maximum": 9007199254740991, "type": "integer" } }, "required": [ "merchant", "products", "contact" ], "type": "object" }, "name": "request_quote", "outputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "next_step": { "type": "string" }, "reference_number": { "type": "string" }, "status": { "type": "string" } }, "type": "object" } }, { "description": "research_shopping is the full verified-research job; find_products is the quick candidate-list tool. It runs as a background job and returns status \"running\" with a research ID while the minutes-long research continues; the same research ID returns the run on later polls until completion. Unsafe medical, legal, financial-advice, and professional-service asks return status \"refused\" before any work is queued. Completed runs return a researched recommendation with per-claim source receipts, or an explicit refusal when evidence is insufficient. Missing decision details return clarification questions before research starts. `market` biases discovery and marketplace checks toward seller pages serving that country; \"available in <market>\" means the seller page serves that market, not that stock is guaranteed. Example answer keys include {\"budget\":\"500 USD\",\"market\":\"US\",\"category\":\"espresso machine\"}.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "answers": { "additionalProperties": {}, "description": "Answers to clarification questions. Set accept_defaults:true to accept budget and market defaults; it does not waive product type, use case, or must-have requirements.", "propertyNames": { "type": "string" }, "type": "object" }, "market": { "description": "Buyer market as an ISO 3166-1 alpha-2 country code. Biases discovery and marketplace checks toward seller pages serving that country; availability is not a stock guarantee.", "type": "string" }, "need": { "description": "Buyer need in natural language. Required when starting a new research run.", "maxLength": 2000, "minLength": 1, "type": "string" }, "persona": { "description": "Research persona; b2b produces a quotation/RFQ pack.", "enum": [ "consumer", "b2b" ], "type": "string" }, "research_id": { "description": "Existing research run identifier to read instead of starting a new run.", "type": "string" } }, "type": "object" }, "name": "research_shopping", "outputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "accepted_defaults": { "additionalProperties": { "type": "string" }, "propertyNames": { "type": "string" }, "type": "object" }, "dossier": {}, "elapsed_seconds": { "type": "number" }, "eta_seconds": { "anyOf": [ { "type": "number" }, { "type": "null" } ] }, "outcome": { "anyOf": [ { "enum": [ "recommend", "conditional", "insufficient_evidence", "no_candidate_passes", "defer" ], "type": "string" }, { "type": "null" } ] }, "questions": { "items": { "additionalProperties": false, "properties": { "key": { "enum": [ "budget", "market", "category" ], "type": "string" }, "question": { "type": "string" } }, "required": [ "key", "question" ], "type": "object" }, "type": "array" }, "reason": { "type": "string" }, "research_id": { "type": "string" }, "stage": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "stage_counters": { "additionalProperties": {}, "description": "Progress counters for a running research job. Individual counters may be absent.", "properties": { "candidates_found": { "description": "Candidates found during discovery.", "type": "number" }, "listings_checked": { "description": "Market listing URLs recorded during commercial checks.", "type": "number" }, "stage": { "description": "Current pipeline stage identifier, or queued before work starts.", "type": "string" }, "verified": { "description": "Candidates examined during verification, not a count of candidates that passed.", "type": "number" } }, "type": "object" }, "status": { "enum": [ "needs_input", "running", "complete", "failed", "refused" ], "type": "string" } }, "required": [ "status" ], "type": "object" } }, { "description": "Search the AirShelf cross-vendor product catalog by natural-language query. The catalog covers industrial-automation, wiring-devices, digital-signage, business-display, mfp, barcode-printer, laser-printer, inkjet-printer, mechanical-keyboards, cybersecurity, threat-intelligence-platform. Industrial-automation and wiring-device rows are indexed by manufacturer part number, so a brand or part number in the query (\"Pepperl+Fuchs retroreflective sensor\", \"IN5409\") retrieves more reliably than a bare product type; those rows carry no normalized spec facets, so the `specs` filter does not apply to them. Returns ranked products with prices, specs, and per-row match accounting.\nEach row includes `unverified_specs`, the normalized spec names that lack claim-level receipts; never use those as decisive facts.\nExample queries: \"tactile mechanical keyboard under $150\", \"Toshiba A3 colour multifunction device\", \"industrial barcode printer for a warehouse\", \"threat-intelligence platform with dark-web monitoring\".\n\nResult fields:\n• canonical_name — the exact catalog name of the product.\n• spec_absence_note — spec fields absent from this product's golden record (AirShelf's verified product record); null when nothing is missing.\n• constraint_match_score and matched_criteria — query constraints supported by claim-level receipts. unverified_criteria names matching catalog values that still need confirmation; missing_criteria names values that are absent or conflict.\n• parsed.price_availability — all_null = true means every returned price is null. For quote-gated B2B pricing, a null price with a quote path is expected rather than an error; query_had_budget reports whether the query carried one.\n• result.commercial_data — branch on actionable before using price or stock. Observations older than 24 hours are withheld from result.price/result.inStock and retained only as labelled last_observed history.\n• parsed.weak_match — the response contains an unresolved constraint, query match, or product-identity warning. parsed.unverified_identity_count counts returned names without an identity receipt. parsed.no_match — no product satisfies a hard constraint, and candidates violating it were excluded server-side.\n\nOn a miss or near-miss for a specific brand+model the response may also carry a `tier3` block, meaning a real-time lookup for the exact SKU asked about; it can appear alongside fuzzy-neighbour rows.\n• tier3.status = \"resolved\" — a single-source reading of the page at tier3.source_url. MPN-confirmed means the live lookup matched the manufacturer part number. Its verification is \"live-unverified\": confirmed on a live page during this run, but not yet matched to an AirShelf catalog record. A verified row is matched to the catalog record. tier3.cached = true means it came from a recent prior lookup, with fetched_at recording when the page was read.\n• tier3.status = \"abstain\" — the lookup could not confirm the product exists as asked, so no specs, price, or availability were established. tier3.guidance describes the quote-request path.\n• tier3.status = \"declined\" — an applicable lookup did not run; tier3.reason says why (disabled, rate_limited, daily_cap, negative_cache, error). No specs or availability were established, and none should be inferred.\nNo tier3 block at all means a live lookup was not applicable to this query (no parseable brand+model identity).\n\nOptional `market` (ISO 3166-1 alpha-2, e.g. \"TH\") excludes catalog rows whose country-specific URL conflicts with the buyer market and scopes tier3 lookup/cache. A remaining global URL is not local-availability proof: parsed.weak_match stays true and unsatisfied_constraints includes market_availability until every returned row has a matching country receipt. \"Available in <market>\" still does not guarantee stock.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "category": { "description": "Optional category filter (industrial-automation, wiring-devices, digital-signage, business-display, mfp, barcode-printer, laser-printer, inkjet-printer, mechanical-keyboards, cybersecurity, threat-intelligence-platform)", "type": "string" }, "limit": { "default": 20, "description": "Max results", "maximum": 200, "minimum": 1, "type": "integer" }, "market": { "description": "Buyer market as an assigned ISO 3166-1 alpha-2 country code (e.g. \"TH\", \"AU\"). Conflicting country receipts are excluded; global URLs remain market-unverified.", "type": "string" }, "merchant": { "description": "Optional merchant slug (e.g. \"toshiba\", \"cyble\") from list_merchants. Scopes the search to that merchant's own shelf, which is a SEPARATE substrate from the cross-vendor catalog: it is reached only when the cross-vendor catalog returns nothing, and its rows carry the merchant's own product data rather than datasheet-extracted golden records. Omit it for cross-vendor search, which is the default and the right choice for \"what should I buy\".", "pattern": "^[a-z0-9][a-z0-9-]{0,62}$", "type": "string" }, "q": { "description": "Natural-language query, at most 200 characters. Supports budget hints (e.g. \"under $150\").", "maxLength": 200, "minLength": 0, "type": "string" }, "specs": { "additionalProperties": { "anyOf": [ { "type": "number" }, { "type": "string" }, { "type": "boolean" } ] }, "description": "Hard spec facets, e.g. {\"form_factor\":\"desktop\",\"print_speed_ppm\":33}. Filters by exact/range spec match.", "propertyNames": { "type": "string" }, "type": "object" } }, "required": [ "q" ], "type": "object" }, "name": "search_catalog", "outputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "count": { "type": "number" }, "parsed": { "additionalProperties": {}, "propertyNames": { "type": "string" }, "type": "object" }, "query": { "type": "string" }, "reason": { "type": "string" }, "results": { "items": { "additionalProperties": {}, "properties": { "canonical_name": { "type": "string" }, "category": { "type": "string" }, "constraint_match_score": { "type": "number" }, "currency": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "manufacturer": { "type": "string" }, "modelName": { "type": "string" }, "price": { "anyOf": [ { "type": "number" }, { "type": "null" } ] }, "qualityScore": { "type": "number" }, "slug": { "type": "string" }, "spec_absence_note": { "anyOf": [ { "type": "string" }, { "type": "null" } ] } }, "required": [ "slug" ], "type": "object" }, "type": "array" }, "status": { "enum": [ "refused" ], "type": "string" }, "tier3": { "additionalProperties": {}, "properties": { "cached": { "type": "boolean" }, "guidance": { "type": "string" }, "identity": { "additionalProperties": false, "properties": { "brand": { "type": "string" }, "model": { "type": "string" } }, "required": [ "brand", "model" ], "type": "object" }, "mpn_confirmed": { "type": "boolean" }, "product": { "additionalProperties": {}, "propertyNames": { "type": "string" }, "type": "object" }, "reason": { "type": "string" }, "source_tier": { "type": "string" }, "source_url": { "type": "string" }, "status": { "enum": [ "resolved", "abstain", "declined" ], "type": "string" }, "tier": { "type": "number" }, "verification": { "type": "string" } }, "required": [ "tier", "status" ], "type": "object" }, "took_ms": { "type": "number" } }, "required": [ "results" ], "type": "object" } } ] }
Verify it yourselfcurl -s https://api.teppi.xyz/v1/evidence/sha256:8e526cd4d8c231472f0fb5c7d63442ffc18ba4c8fa4e4f283ce4db94c73dd945 | sha256sum