gridscoot
mcp tools

The 7 tools

Reference for every Gridscoot MCP tool — inputs, outputs, example calls, and the error modes worth handling.

Overview

The Gridscoot MCP server publishes seven tools — six price-discovery tools (parity with best-in-class aggregators per ADR-0006) and one novel alternatives engine (find_alternatives, Phase 14.4). Each is documented below with its input schema, output schema, and an example call. Schemas are returned by the live server’s tools/list response in the canonical machine-readable form; this page is the human-readable companion.

The free tier (60 requests / minute, anonymous) covers six of the seven tools. find_alternatives requires a Bearer key (no demo tier — the alternatives engine is heavier per request than search and the cost would be prohibitive to expose anonymously). Authenticated tiers raise the rate limit on all tools and unlock track_price's alert subscription.

search_products

Search the deduped catalogue by free-text query, with optional price + retailer + GTIN filters.

Input

input
{
  "query": "sony wh-1000xm5",          // required; free-text + GTIN supported
  "max_price_aud": 600,                  // optional; integer cents internally
  "min_price_aud": 200,                  // optional
  "retailer_slug": "ebay-au",            // optional; restrict to one retailer
  "page_size": 20                         // optional; default 20, max 50
}

Output

response
{
  "query": "sony wh-1000xm5",
  "results": [
    {
      "product": {
        "id": "1",
        "title": "Sony WH-1000XM5",
        "brand": "Sony",
        "mpn": "WH1000XM5B",
        "gtin": "4548736133075",
        "category_path": ["electronics","audio","headphones"]
      },
      "best_offer": {
        "retailer": { "slug": "ebay-au", "name": "eBay Australia" },
        "price_aud": 445.55,
        "shipping_aud": 12.40,
        "total_aud": 457.95,
        "in_stock": true,
        "product_url": "https://ebay.illustrative.gridscoot.invalid/..."
      },
      "match_confidence": "high"          // 'high' | 'medium' | 'low'
    }
  ],
  "query_meta": {
    "search_method": "pg_trgm + word_similarity + pgvector",
    "data_source_advisory": "Early-access catalogue: ..."
  }
}

compare_product

Return every in-stock offer for a single canonical product across all retailers. Used after search_products picks the canonical match.

Input

input
{
  "product_id": "1"                       // required; canonical product id
}

Output

response
{
  "product": { "id": "1", "title": "...", "brand": "Sony", "mpn": "WH1000XM5B" },
  "offers": [
    {
      "retailer": { "slug": "ebay-au", "name": "eBay Australia" },
      "price_aud": 445.55,
      "shipping_aud": 12.40,
      "total_aud": 457.95,
      "in_stock": true,
      "product_url": "..."
    }
    // ... more offers, sorted cheapest-total-first
  ]
}

get_price_history

Price history series with fake-discount flagging. Default window 90 days.

Input

input
{
  "product_id": "1",
  "window_days": 90                       // 30 | 90 | 365; default 90
}

Output

response
{
  "product_id": "1",
  "window_days": 90,
  "series": [
    { "date": "2026-05-26", "price_aud": 459.00, "in_stock": true },
    { "date": "2026-05-25", "price_aud": 459.00, "in_stock": true }
    // ...
  ],
  "stats": {
    "current_aud": 445.55,
    "median_aud": 459.00,
    "min_aud": 419.00,
    "max_aud": 549.00,
    "fake_discount_flag": false           // true if "was" price > 30-day median
  }
}

check_availability

Live in-stock + ETA check at a specific retailer. Wraps the retailer’s most recent feed snapshot.

Input

input
{
  "product_id": "1",
  "retailer_slug": "ebay-au"
}

Output

response
{
  "product_id": "1",
  "retailer_slug": "ebay-au",
  "in_stock": true,
  "feed_freshness_minutes": 14,           // minutes since last successful pull
  "delivery_eta_business_days": "2-5",
  "product_url": "..."
}

list_retailers

Active retailer feeds + status. Mirrors what the public /status page shows.

Input

None. Returns the full active-retailer roster.

Output

response
{
  "retailers": [
    {
      "slug": "ebay-au",
      "name": "eBay Australia",
      "network": "ebay-partner-network",
      "country": "AU",
      "last_pull_at": "2026-05-28T03:14:00Z",
      "is_stale": false
    }
    // ...
  ]
}

track_price

Subscribe to a price-drop alert. Pro tier only — the free tier returns a structured 403 with the upgrade path.

Input

input
{
  "product_id": "1",
  "target_price_aud": 399.00,             // required; integer cents internally
  "email": "you@example.com"              // required when called anonymously
}

Output

response
{
  "alert_id": "alt_1a2b3c4d",
  "product_id": "1",
  "target_price_aud": 399.00,
  "active": true,
  "notify_via": "email",
  "created_at": "2026-05-28T03:14:00Z"
}

find_alternatives

Given a baseline product (the user’s current pick) + a buyer country, return the qualifying equal-or-better alternatives ranked by delivered total. Phase 14.4 addition, extended in Phase 14.4.1a (DB-lookup mode); the surface is novel — no other DACH/AU/EU aggregator exposes a strict meets-or-exceeds + cross-border delivered-total comparison via a typed agent surface. Use after search_products when you want to evaluate a baseline against alternatives, either with your own candidate set (inline mode) or against the Gridscoot catalog (DB-lookup mode).

Two input modes

  • Inline mode (Phase 14.4 default). You pass baseline + candidates[] + the usual options. Use when you already have a candidate set in hand — e.g. you ran search_products and curated the results to a same-category subset.
  • DB-lookup mode (Phase 14.4.1a). You pass baselineProductId + buyerCountry (+ optional categorySchemaSlug / maxCandidates). The server resolves both the baseline and same-category candidates from the catalog itself, synthesises shipping / OSS where data is missing, and discloses what was synthesised on the response under catalogResolution.synthesizedFields[]. Massively simpler agent payload — ~5 lines vs a 50+ line inline payload.

Server-enforced invariants

  • List price only. Vouchers, promo codes, loyalty pricing — never read. Pass the catalogue list price (incl. seller-country VAT, the EU B2C-published shape) on listPriceInclSellerVat.
  • Strict meets-or-exceeds. Every declared baseline spec is a hard floor. IP67 ≠ IP69; IP68 fails an IP69 baseline. Numeric specs honour lowerIsBetter (e.g. accuracy_celsius: ±0.1°C beats ±0.5°C).
  • Honest unknowns. Undeclared candidate specs disqualify with a spec_unknown reason. We refuse to assume.
  • Cross-border VAT differential. Delivered total is computed as list_price + cheapest_ship_to_buyer + vat_diff under EU OSS rules. A €59.99 (DE 19%) list price delivered to HU (27%) becomes ~€64.02 — the differential is real and you should never compare bare list prices across borders.

Ranking (ADR-0007)

Default trustWeight=0 sorts by delivered total ascending — pure cheapest. Opt-in trustWeight ∈ (0,1] blends in a merchant trust_score with the formula weighted = (1 - tw) × price_score + tw × trust_score. Both the formula and the per-candidate inputs travel back in the response. See /rankings for the full algorithm disclosure.

Input — DB-lookup mode (Phase 14.4.1a, recommended)

input · db-lookup
{
  "baselineProductId": 1,            // canonical_products.id
  "buyerCountry": "HU",              // ISO 3166-1 alpha-2
  "categorySchemaSlug": null,         // optional; server derives from category_path
  "maxCandidates": 50,                // optional; max same-category rows to consider
  "trustWeight": 0,                   // 0 default = pure cheapest; 1 = trust-only
  "includeSkipped": true,
  "maxResults": 10
}

Input — Inline mode (Phase 14.4)

input · inline
{
  "baseline": {
    "id": "amazon-de:B0F3X7M2LM",
    "displayName": "Meatmeet S Pro · IP69 · 6-probe",
    "currency": "EUR",
    "listPriceInclSellerVat": 87.13,
    "shippingQuotes": [
      { "carrierSlug": "amazon-prime", "costMajor": 0,
        "shipsToCountries": ["DE","AT","HU"] }
    ],
    "sellerCountry": "DE",
    "sellerOssStatus": "oss_registered",
    "rawSpecs": {
      "sensor_count": 6,
      "accuracy_celsius": 0.1,
      "ip_rating": "IP69"
    }
  },
  "candidates": [
    // up to 200 candidate offers, same shape as baseline
  ],
  "buyerCountry": "HU",
  "categorySchemaSlug": "kitchen-appliances/meat-thermometer",
  "trustWeight": 0,
  "includeSkipped": true,
  "maxResults": 10
}

Output

response
{
  "baseline": {
    "id": "amazon-de:B0F3X7M2LM",
    "deliveredTotal": 92.91,
    "deliveredCurrency": "EUR",
    "breakdown": {
      "listPriceInclSellerVat": 87.13,
      "sellerCountryVatPct": 19,
      "buyerCountryVatPct": 27,
      "shippingMajor": 0,
      "vatDifferentialMajor": 5.78
    }
  },
  "alternatives": [
    // qualifying candidates, sorted by ranking policy
    // each row has: id, displayName, deliveredTotal, breakdown,
    // matchedSpecs[], trustScore (when trustWeight > 0)
  ],
  "skipped": [
    {
      "id": "amazon-de:B0BW8B6LDG",
      "reason": "spec_below_floor",
      "detail": "ip_rating=IP67 < baseline IP69"
    }
    // ... one row per candidate that failed
  ],
  "surveyedCount": 3,
  "rankingPolicy": {
    "trustWeight": 0,
    "formula": "sort by deliveredTotal ascending (pure-cheapest default per ADR-0007)"
  },
  "honestEmpty": true,         // true when zero candidates qualified
  "honestEmptyReason": "Of 3 surveyed, 3 skipped. No candidate meets-or-exceeds every declared baseline spec while shipping to HU.",

  // Only present in DB-lookup mode — discloses what was real catalog
  // data vs best-effort synthesis (because the catalog doesn't yet
  // store multi-carrier shipping or per-retailer OSS status):
  "catalogResolution": {
    "baselineProductId": 1,
    "resolvedCategorySchemaSlug": "kitchen-appliances/meat-thermometer",
    "synthesizedFields": ["sellerOssStatus", "shippingQuotes"],
    "surveyedProductCount": 2,
    "notes": [
      "shippingQuotes synthesised from single offers.shipping_cents per offer...",
      "sellerOssStatus best-effort: known large EU sellers hard-coded; otherwise 'unknown'."
    ]
  }
}

Category schemas

The categorySchemaSlug field selects which spec keys are treated as required hard floors. Registered slugs: kitchen-appliances/blender, kitchen-appliances/meat-thermometer, garden/hose, household/kids-sprinkler, household/cabinet-hardware/knob, energy-rated-appliance, tyre, wine, cosmetic, pharma.

Common errors

Errors follow JSON-RPC convention. The top-level shape:

error
{
  "error": {
    "code": -32602,                       // JSON-RPC error code
    "message": "Invalid params",
    "data": {                             // structured details
      "kind": "validation",
      "field": "max_price_aud",
      "reason": "must be a positive number"
    }
  }
}

Codes you’ll see

  • -32602 — input validation (your inputs)
  • -32603 — internal (our problem; retry with exponential backoff)
  • -32000 — rate limit exceeded (retry after the retry_after_seconds in data)
  • -32001 — auth (Pro-tier-only tool called from free tier)