Skip to main content
Glama
JavidGlyv

Turbo.az MCP Server

by JavidGlyv

search_cars

Search for vehicles on Turbo.az using filters like make, model, price range, year, fuel type, and transmission to find matching car listings.

Instructions

Car search on Turbo.az. Search by make, model, price range, year, etc.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
makeNoCar make (e.g. BMW, Mercedes, Toyota)
modelNoCar model (e.g. X5, E-Class, Camry)
price_minNoMinimum price (AZN)
price_maxNoMaximum price (AZN)
year_minNoMinimum year of manufacture
year_maxNoMaximum year of manufacture
fuel_typeNoFuel type: petrol, diesel, gas, electric, hybrid
transmissionNoTransmission: automatic, manual
limitNoResult count limit (default: 20)

Implementation Reference

  • The handler function search_cars which performs the web scraping of car listings.
    async def search_cars(
        self,
        make: Optional[str] = None,
        model: Optional[str] = None,
        price_min: Optional[int] = None,
        price_max: Optional[int] = None,
        year_min: Optional[int] = None,
        year_max: Optional[int] = None,
        fuel_type: Optional[str] = None,
        transmission: Optional[str] = None,
        limit: int = 20
    ) -> dict:
        """Searches for cars (gets ID from make/model name and builds full URL)."""
        fuel_mapping = {
            "benzin": 1, "dizel": 2, "qaz": 3, "elektrik": 6, "hibrid": 7, "plug-in hibrid": 8,
        }
        transmission_mapping = {
            "mexaniki": 1, "avtomat": 2, "robot": 3, "variator": 4,
        }
        fuel_id = fuel_mapping.get((fuel_type or "").lower()) if fuel_type else None
        transmission_id = transmission_mapping.get((transmission or "").lower()) if transmission else None
    
        def _scrape():
            driver = self._get_driver()
            results = []
            make_id = None
            model_id = None
            try:
                if make:
                    driver.get(f"{BASE_URL}/autos")
                    WebDriverWait(driver, 20).until(
                        EC.presence_of_element_located((By.CSS_SELECTOR, '.tz-dropdown[data-id="q_make"]'))
                    )
                    time.sleep(0.3)
                    try:
                        driver.find_element(By.CSS_SELECTOR, '.tz-dropdown[data-id="q_make"] .tz-dropdown__selected').click()
                        time.sleep(0.2)
                    except Exception:
                        pass
                    make_opts = self._parse_tz_dropdown_options(driver, "q_make")
                    make_lower = make.strip().lower()
                    for val, label in make_opts:
                        txt = label.lower()
                        if txt == make_lower or txt.startswith(make_lower + " ") or txt.startswith(make_lower + "(") or make_lower in txt:
                            make_id = val
                            break
                    if not make_id:
                        all_makes = [label for _, label in make_opts[:20]]
                        logger.warning("Make not found. Sample options: %s", all_makes)
                        return {"success": False, "error": f"Make not found: {make}"}
                    if model:
                        # Open make dropdown and click make option so model list is populated
                        try:
                            make_cont = driver.find_element(By.CSS_SELECTOR, '.tz-dropdown[data-id="q_make"]')
                            make_cont.find_element(By.CSS_SELECTOR, ".tz-dropdown__selected").click()
                            time.sleep(0.3)
                            opts_el = make_cont.find_elements(By.CSS_SELECTOR, ".tz-dropdown__list .tz-dropdown__option")
                            for el in opts_el:
                                if (el.get_attribute("data-val") or "").strip() == make_id:
                                    el.click()
                                    break
                            time.sleep(0.5)
                        except Exception:
                            pass
                        # Open model dropdown so options are in DOM
                        try:
                            driver.find_element(By.CSS_SELECTOR, '.tz-dropdown[data-id="q_model"] .tz-dropdown__selected').click()
                            time.sleep(0.2)
                        except Exception:
                            pass
                        model_opts = self._parse_tz_dropdown_options(driver, "q_model")
                        model_lower = model.strip().lower()
                        for val, label in model_opts:
                            txt = label.lower()
                            if txt == model_lower or txt.startswith(model_lower + " ") or txt.startswith(model_lower + "("):
                                model_id = val
                                break
                url = self._build_search_url(
                    make_id=make_id,
                    model_id=model_id,
                    price_min=price_min,
                    price_max=price_max,
                    year_min=year_min,
                    year_max=year_max,
                    fuel_id=fuel_id,
                    transmission_id=transmission_id,
                )
                logger.info(f"Searching: {url}")
                driver.get(url)
                WebDriverWait(driver, 20).until(
                    EC.presence_of_element_located((By.CLASS_NAME, "products-i"))
                )
    
                # Find listings
                items = driver.find_elements(By.CLASS_NAME, "products-i")[:limit]
                
                for item in items:
                    try:
                        car = {}
    
                        # Title and link
                        link_elem = item.find_element(By.CLASS_NAME, "products-i__link")
                        car["url"] = link_elem.get_attribute("href")
                        car["id"] = car["url"].split("/")[-1].split("-")[0]
    
                        # Image
                        try:
                            img = item.find_element(By.CSS_SELECTOR, ".products-i__top img")
                            car["image"] = img.get_attribute("src")
                        except NoSuchElementException:
                            car["image"] = None
    
                        # Title (make + model)
                        try:
                            title = item.find_element(By.CLASS_NAME, "products-i__name")
                            car["title"] = title.text.strip()
                        except NoSuchElementException:
                            car["title"] = "N/A"
    
                        # Price
                        try:
                            price = item.find_element(By.CLASS_NAME, "products-i__price")
                            car["price"] = price.text.strip()
                        except NoSuchElementException:
                            car["price"] = "N/A"
    
                        # Additional info (year, engine, mileage)
                        try:
                            attrs = item.find_elements(By.CLASS_NAME, "products-i__attributes")
                            if attrs:
                                attr_text = attrs[0].text.strip()
                                parts = [p.strip() for p in attr_text.split(",")]
                                if len(parts) >= 1:
                                    car["year"] = parts[0]
                                if len(parts) >= 2:
                                    car["engine"] = parts[1]
                                if len(parts) >= 3:
                                    car["mileage"] = parts[2]
                        except NoSuchElementException:
                            pass
  • src/server.py:87-115 (registration)
    Registration of the search_cars tool in the MCP server using the list_tools decorator.
    Tool(
        name="search_cars",
        description="Car search on Turbo.az. Search by make, model, price range, year, etc.",
        inputSchema={
            "type": "object",
            "properties": {
                "make": {
                    "type": "string",
                    "description": "Car make (e.g. BMW, Mercedes, Toyota)"
                },
                "model": {
                    "type": "string",
                    "description": "Car model (e.g. X5, E-Class, Camry)"
                },
                "price_min": {
                    "type": "integer",
                    "description": "Minimum price (AZN)"
                },
                "price_max": {
                    "type": "integer",
                    "description": "Maximum price (AZN)"
                },
                "year_min": {
                    "type": "integer",
                    "description": "Minimum year of manufacture"
                },
                "year_max": {
                    "type": "integer",
                    "description": "Maximum year of manufacture"

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/JavidGlyv/Turboaz-MCP'

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