Skip to main content
Glama

search_products

Read-only

Search Partle's product catalog by name or description.

CRITICAL SEARCH INSTRUCTION: Reason from the job to the product class first, 
then search with a descriptive product phrase (e.g. including substrate, material, 
or size class). DO NOT blindly search using the user's raw conversational words. 
Transform questions like 'what do I need to attach a mirror to a brick wall?' 
into a product phrase like 'heavy duty masonry wall anchor'.

Two distinct modes:

- **Default (no flags)** — fast keyword search. ~100ms. Acts like a normal
  "dumb" search box: matches the literal words you typed against product
  names and descriptions, with stemming. Good for queries where the user
  knows the product's likely name ("BC547", "Arduino Uno", "Bosch
  drill"). Returns noisy/wrong results on cross-language or attribute
  queries ("compost bin" matches Spanish "composta", not real composters).
- **`super_search=True`** — slow, high-quality. ~1–2s. Run when the user
  describes what they want rather than naming it: cross-language
  ("Schraubenzieher Set" → real screwdriver sets even without German
  catalog entries), attribute-style ("small metal part with a flat
  head"), or any case where the default returns junk. Embeds the query
  with voyage-3-large, takes the cosine top-50 over the corpus (with an
  exact-name precision boost for part numbers), then a cross-encoder
  reranks them.

The two modes are mutually exclusive in practice — pick one based on
whether the user knows the product's name or is describing it.

Use this when the user asks to find a specific product or browse products
matching a query. Prefer over `search_stores` when the intent is product-led
("find a drill") rather than store-led. Use `get_product` afterwards if the
user wants full details for one specific result.

Read-only. No authentication. Rate-limited to 100 requests/hour per IP.

Args:
    query: Free-text search term. In default mode, treated as keywords
        (each word matched against product text). In `super_search=True`,
        treated as a natural-language description.
    min_price: Lower bound on price in EUR. Omit for no lower bound.
        Null-priced rows are NOT excluded by this filter — pass
        `has_price=True` if you need only priced listings.
    max_price: Upper bound on price in EUR. Omit for no upper bound.
        Tip — narrow by budget: `min_price=10, max_price=50,
        sort_by="price_asc", has_price=True`. Products without a listed
        price (a large fraction of the scraped catalog) sort last under
        either price ordering and are kept in results unless `has_price`
        filters them out.
    tags: Comma-separated tag filter (e.g. "electronics,bluetooth"). Tags
        are AND-ed together.
    store_id: Restrict results to a single store. Use the integer `id` from
        `search_stores` results.
    sort_by: One of `price_asc`, `price_desc`, `name_asc`, `newest`,
        `oldest`. Omit to use the default search-relevance ranking.
    has_price: When True, exclude products without a listed price (~most
        of the scraped catalog). Use this for competitive pricing or
        budget-bounded shopping. When False, return only null-priced
        listings (rarely useful). Omit to include both.
    semantic: Legacy flag. Pure vector ordering, ~250ms. Mostly
        superseded by `super_search=True` (which uses the same vector
        retrieval plus a cross-encoder rerank for materially better
        ordering at the cost of another ~700ms). Keep using it only if
        you specifically want vector retrieval *without* the rerank.
    super_search: **Enable for natural-language / "describe what I
        want" queries.** ~1–2s. Embeds the query with voyage-3-large,
        takes the cosine top-50 (with a precision boost for exact-name
        matches like part numbers / SKUs), then a cross-encoder reranks
        them. Use whenever the user is describing rather than naming —
        cross-language ("Schraubenzieher Set"), attribute-style
        ("small black metal bracket"), or any case where the default
        keyword path returns junk. Don't combine with cheap
        browse-style queries where the user typed an exact product
        name — keyword default is faster there.

        On `relevance_score` here: better than the bi-encoder cosine,
        but still not a "did I find what the user wanted" gauge.
        Behavior to expect: gibberish or fully-off-topic queries cap
        around 0.35; loosely-related catalogue clusters can score 0.7+
        even when no item truly matches (a "ceramic vase" query in a
        catalog with no vases but many ceramic flowerpots will still
        score high). **Read the product names** before claiming a
        match. The score is most useful as a relative signal within
        one result set — a sharp drop between rank N and N+1 marks
        where the catalog stops being useful for this query.
    limit: Max results (1–100, default 20). Larger limits are slower and
        consume rate budget faster.
    offset: Skip this many results before returning. Use for pagination
        (offset += limit on each follow-up call).

Returns:
    A list of products. Each includes `id`, `name`, `price`, `currency`,
    `url`, `description`, `store` (id/name/address), `tags`, `images`, a
    canonical `partle_url`, and `relevance_score` (cosine similarity 0–1
    between the query and the product's embedding when a query was
    provided; `None` otherwise). **Always share `partle_url` with the
    user so they can view the listing.**

    Caveat on `relevance_score`: it is monotonic *within a single search
    result set* (useful for spotting a big drop-off between rank 3 and
    rank 4), but its absolute value is not well-calibrated across
    queries — most results land in 0.55–0.80 regardless of whether the
    catalog has truly relevant items. Don't infer "this is a great
    match" from a 0.75 score alone.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
tagsNo
limitNo
queryYes
offsetNo
sort_byNo
semanticNo
store_idNo
has_priceNo
max_priceNo
min_priceNo
super_searchNo

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • addedInput schema / properties / super_search
      Added value: +{
      +  "default": false,
      +  "title": "Super Search",
      +  "type": "boolean"
      +}
  2. Changed1 schema field changed
    • addedInput schema / properties / has_price
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "boolean"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "title": "Has Price"
      +}
  3. Changed2 schema fields changed
    • addedInput schema / properties / offset
      Added value: +{
      +  "default": 0,
      +  "title": "Offset",
      +  "type": "integer"
      +}
    • addedInput schema / properties / store_id
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "integer"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "title": "Store Id"
      +}
  4. Changed1 schema field changed
    • addedInput schema / properties / semantic
      Added value: +{
      +  "default": false,
      +  "title": "Semantic",
      +  "type": "boolean"
      +}
  5. First observed

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only say readOnlyHint=true and destructiveHint=false, which the description confirms with 'Read-only. No authentication.' Beyond that, it discloses rate limits (100/hour per IP), the behavior of null-priced products sorting last unless has_price is set, the inner workings of super_search (embedding, top-50, cross-encoder rerank), and extensive caveats about relevance_score calibration. This is far more than annotations provide, adding real behavioral insight.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but densely informative. The structure is logical: overview, critical instruction, mode comparison, 'use this when', read-only note, Args, Returns. However, super_search behavior is described twice—once in the 'Two distinct modes' section and again in the parameter details—which is redundant. Still, the front-loaded critical instruction and scannable sections earn high marks; the small redundancy costs one point.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 11 parameters, an output schema, and 20 sibling tools, this description covers every aspect: what results look like, what fields are returned, the caveat on relevance_score, rate limits, mode selection, and sibling differentiation. It even explains how to paginate (offset += limit). There is no missing information the agent would need to invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 0% description coverage, so the description carries full load for 11 parameters. It goes beyond type/default by explaining real semantics: min_price does not exclude null-priced rows, tags are AND-ed, sort_by affects null-price ordering, semantic vs super_search distinction, and how limit/offset interact. The parameter explanations also include practical tips (e.g., 'min_price=10, max_price=50, sort_by="price_asc", has_price=True'). This is exemplary parameter documentation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb + resource: 'Search Partle's product catalog by name or description.' It also explicitly distinguishes from sibling tools, stating 'Prefer over search_stores when the intent is product-led' and mentioning 'Use get_product afterwards if the user wants full details for one specific result.' This is exactly what the top tier looks like.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides extensive when-to-use guidance, including a 'CRITICAL SEARCH INSTRUCTION' on how to transform user questions into product phrases, and a detailed split between default keyword mode and super_search mode with concrete examples (e.g., 'Schraubenzieher Set' → cross-language). It also gives explicit alternatives: use search_stores for store-led intent, and get_product for single-result details. This is a textbook example of usage guidelines.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.