Skip to main content
Glama

product_search

Search for products across e-commerce platforms by entering a natural language query.

Instructions

Product Search

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYesSearch query

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • The main handler function for the 'product_search' tool. It accepts a 'query' string via Annotated Field, retrieves the server setting from the context, calls ProductSearchService.search(), and returns a slim JSON dump of the ProductSearchToolResponse.
    async def product_search(
        ctx: Context,
        query: Annotated[
            str,
            Field(
                description="""Search query""",
                examples=["iphone", "護唇膏"],
            ),
        ],
    ) -> str:
        """Product Search"""
        logger.info("product search, query: %s", query)
    
        setting = get_setting(ctx)
        service = ProductSearchService(setting)
        ret = await service.search(query)
    
        return ProductSearchToolResponse(product_search_result=ret).slim_dump()
  • ProductSearchService contains the core business logic: calls the BigGo API (https://api.biggo.com/api/v1/spa/search/{query}/product) with domain/region headers, parses the response into ProductSearchAPIRet, generates real product URLs, and optionally shortens URLs.
    class ProductSearchService:
        def __init__(self, setting: BigGoMCPSetting):
            self._setting = setting
    
        async def search(self, query: str) -> ProductSearchAPIRet:
            url = f"https://api.biggo.com/api/v1/spa/search/{query}/product"
    
            headers = {
                "Content-Type": "application/json",
                "site": self._setting.domain.value,
                "region": self._setting.region.value.lower(),
            }
            logger.debug("product search, url: %s, headers: %s", url, headers)
    
            async with ClientSession() as session:
                async with session.get(url, headers=headers) as resp:
                    if resp.status >= 400:
                        err_msg = f"product search api error: {await resp.text()}"
                        logger.error(err_msg)
                        raise ValueError(err_msg)
    
                    data = ProductSearchAPIRet.model_validate(await resp.json())
    
            data.generate_r_link(self._setting.domain)
    
            if self._setting.short_url_endpoint is not None:
                all_urls = data.get_all_urls()
                url_map = await generate_short_url(
                    list(all_urls), self._setting.short_url_endpoint
                )
                data.replace_urls(url_map)
    
            return data
  • Registration: The tool is registered via 'server.add_tool(product_search)' where product_search is imported from ..tools.product_search.
    async def create_server(setting: BigGoMCPSetting) -> BigGoMCPServer:
        server = BigGoMCPServer(setting)
        setup_logging(setting.log_level)
    
        # Product Search
        server.add_tool(product_search)
    
        # Price History
        # server.add_tool(price_history_graph)
        # server.add_tool(price_history_with_history_id)
        server.add_tool(price_history_with_url)
    
        # Spec Search
        # server.add_tool(spec_indexes)
        # server.add_tool(spec_mapping)
        # server.add_tool(spec_search)
    
        return server
  • Pydantic model ProductSearchAPIRet defines the API response schema (list of ListItem, low_price, high_price) with helper methods to generate real URLs, collect all URLs, and replace them with short URLs.
    class ProductSearchAPIRet(BaseModel):
        # result: bool
        # total: int
        # total_page: int
        # pure_total: int
        # ec_count: int
        # mall_count: int
        # bid_count: int
        # size: int
        # took: int
        # is_shop: bool
        # is_suggest_query: bool
        # is_ypa: bool
        # is_adsense: bool
        # q_suggest: str
        # arr_suggest: List[str]
        # offline_count: int
        # spam_count: int
        # promo: List
        # filter: Dict[str, Any]
        # top_ad_count: int
        # group: Any
        # recommend_group: List
        list: List[ListItem] = Field(default_factory=list)
        # biggo_c: List[BiggoCItem]
        low_price: float = 0
        high_price: float = 0
    
        def generate_r_link(self, domain: Domains):
            for product in self.list:
                product.url = f"https://{domain.value}{product.affurl}"
                product.affurl = None
    
        def get_all_urls(self) -> set[str]:
            product_urls = {product.url for product in self.list}
            image_urls = {product.image for product in self.list}
            return product_urls | image_urls
    
        def replace_urls(self, url_map: dict[str, str]):
            """Replace urls in the list with the new urls
    
            Args:
                url_map (dict[str, str]): The map of old urls to new urls
            """
            for product in self.list:
                if product.url in url_map:
                    product.url = url_map[product.url]
                if product.image in url_map:
                    product.image = url_map[product.image]
  • ProductSearchToolResponse wraps the ProductSearchAPIRet result and includes post-initialization logic that sets a 'reason' when no results are found, or 'display_rules' when results exist, and uses slim_dump() for JSON serialization.
    class BaseToolResponse(BaseModel):
        def slim_dump(self) -> str:
            return self.model_dump_json(exclude_none=True, exclude_defaults=True)
    
    
    class ProductSearchToolResponse(BaseToolResponse):
        product_search_result: ProductSearchAPIRet
        reason: str | None = None
        display_rules: str | None = None
    
        @model_validator(mode="after")
        def post_init(self) -> Self:
            if len(self.product_search_result.list) == 0:
                self.reason = """
    No results found. Possible reasons:
    1. This search is much more complex than a simple product search.
    2. The user is asking things related to product specifications.
    
    If the problems might be related to the points listed above,
    please use the 'spec_search' tool and try again.
                """
                return self
    
            # add display rules if result is not empty
            else:
                self.display_rules = """
    As a product researcher, you need to find the most relavent product and present them in utmost detail.
    Without following the rules listed bellow, the output will become useless, you must follow the rules before responding to the user.
    All rules must be followed strictly.
    
    Here are a list of rules you must follow:
    Rule 1: Product image must be included when available, url is located in each object inside 'specs.images' field.
    Rule 2: If no avaliable image exist, ignore the image field completely, don't even write anything image related for that single product.
    Rule 3: Product urls must be included so that the user can by the product with a simple click if possible.
    Rule 4: Display more then one relavent product if possible, having multiple choices is a good thing.
                """
    
            return self
Behavior1/5

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

No annotations are provided, and the description does not disclose any behavioral traits (e.g., request limits, authentication needs, side effects). The description is minimal and adds no transparency.

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

Conciseness1/5

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

The description is two words, which is not an appropriate size. It is under-specification rather than conciseness, as it fails to provide any useful information beyond the tool name.

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

Completeness1/5

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

Despite having an output schema, the description gives no context about the tool's behavior, return values, or when to use it. It is completely inadequate for a tool with 1 parameter and a sibling tool.

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

Parameters3/5

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

Schema coverage is 100% with a single parameter 'query' described as 'Search query' with examples. The description adds no extra meaning beyond the schema, so the baseline score of 3 applies.

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

Purpose1/5

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

The description is just 'Product Search', which is a tautology of the tool name. It does not specify a verb or resource, and does not distinguish it from the sibling tool 'price_history_with_url'.

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

Usage Guidelines1/5

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

The description provides no guidance on when to use this tool or when to avoid it. No alternatives or context are mentioned.

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

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Funmula-Corp/BigGo-MCP-Server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server