Skip to main content
Glama
pik-mcp

pik-mcp

by dkasipovic

pik-mcp

An MCP server that exposes the OLX.ba marketplace API (base URL https://api.olx.ba, documentation) as tools an LLM client can call: authenticate, browse and manage listings, read categories/attributes/locations, and run sponsorship/discount actions.

Setup

npm install
npm run build

Copy .env.example to .env and fill in your OLX credentials:

OLX_USERNAME=your-username-or-email
OLX_PASSWORD=your-password
OLX_DEVICE_NAME=pik-mcp          # optional
OLX_BASE_URL=https://api.olx.ba  # optional

The server logs in with these credentials on the first tool call, caches the bearer token in memory, and automatically re-authenticates if the token expires (HTTP 401). Credentials are never written to stdout (the MCP transport); logs go to stderr.

Related MCP server: meloqa-mcp

Running

pik-mcp speaks MCP over stdio. Point any MCP client at node dist/index.js.

Claude Desktop / Claude Code config

{
  "mcpServers": {
    "olx": {
      "command": "node",
      "args": ["C:/Users/dkasi/Documents/Projects/pik-mcp/dist/index.js"],
      "env": {
        "OLX_USERNAME": "your-username-or-email",
        "OLX_PASSWORD": "your-password"
      }
    }
  }
}

Inspect / debug

npm run inspect   # opens @modelcontextprotocol/inspector against the server

Tools

Group

Tools

Auth

whoami, login_status

Listings (read)

search_listings, get_listing, get_user_listings

Categories

list_categories, get_category_children, get_category, get_category_attributes, get_category_brands, get_category_models, suggest_category, find_category

Locations

list_countries, list_cities, get_city, list_country_states, get_canton_cities

Listings (write)

create_listing, update_listing, publish_listing, refresh_listing, get_refresh_limits, get_listing_limits, finish_listing, hide_listing, unhide_listing, delete_listing

Images

upload_listing_image, delete_listing_image, set_main_listing_image

Sponsored / discount

get_sponsor_price, sponsor_listing, set_listing_discount, finish_listing_discount

Destructive tools (delete_listing, finish_listing, image delete) and paid tools (sponsor_listing, set_listing_discount) are flagged via MCP annotations and their descriptions. refresh_listing may consume a paid refresh once the free quota is exhausted — check get_refresh_limits first.

Searching listings

search_listings performs full-text search over OLX (GET /search). It is public and works without credentials, so you can browse even before setting up login. It accepts typed filters — q, category_id, brand_id, city_id, price_from/price_to, state (condition id, e.g. 2 = used), created_gte (e.g. "-24 hours"), per_page, page, sort_by/sort_order — plus an extra_params object passed through verbatim for advanced keys such as attribute filters (attr, attr_encoded).

By default it returns a compact summary per listing (id, title, price, category/brand/city ids, condition, date, cover image, and a https://olx.ba/artikal/{id} URL) alongside pagination meta and category aggregations. Pass raw: true to get the full untrimmed API payload.

Typical create-and-publish flow

  1. suggest_category / find_category → pick a category_id

  2. get_category_attributes → see required attributes; get_category_brands / get_category_models if applicable

  3. get_city (or list_cities) → pick a city_id

  4. create_listing → returns a DRAFT listing id

  5. upload_listing_image → attach photos; set_main_listing_image for the cover

  6. publish_listing → makes it visible in search

Notes / limitations

  • The documented API exposes no generic "search all listings" endpoint. Browsing is done via categories + a user's listings (get_user_listings).

  • Some success messages from OLX are in Bosnian (e.g. "Oglas je uspjesno objavljen") and are passed through as-is.

Project layout

src/
  index.ts          entry point (stdio transport)
  server.ts         builds McpServer, registers all tool groups
  config.ts         env-based configuration
  olx/
    client.ts       HTTP client: auth, token cache, 401 retry, error mapping
    types.ts        response shapes
  tools/            one file per resource group
  util/             shared zod schemas + result formatting

Available Tools

35 tools
create_listingCreate listing (draft)A

Create a new listing in DRAFT status (POST /listings). Only title is required. The listing is NOT visible until you call publish_listing. Resolve category_id via the category tools and city_id via the location tools first.

Inputs: title (required), price, state, city_id, +10 more.

delete_listingDelete listing (permanent)A
Destructive

PERMANENTLY delete a listing (DELETE /listings/:id). This is irreversible — confirm with the user before calling.

Inputs: id (required).

delete_listing_imageDelete listing imageA
Destructive

Remove one image from a listing (POST /listings/:id/image-delete).

Inputs: id (required), imageId (required).

find_categoryFind category by nameA
Read-only

Find categories matching a name, with their hierarchical path (GET /categories/find?name=).

Inputs: name (required).

finish_listingFinish listing (mark sold)A
Destructive

Mark a listing as completed/sold (POST /listings/:id/finish). This ends the active listing; it moves to the user's finished listings.

Inputs: id (required).

finish_listing_discountFinish listing discountA

End an active discount early and restore the original price (POST /listings/:id/discount/finish).

Inputs: id (required).

get_canton_citiesGet cities in a cantonA
Read-only

Return the cities within a canton (GET /cantons/:id/cities).

Inputs: id (required).

get_categoryGet category detailA
Read-only

Return a single category with detailed properties such as base_listing_price and top_category status (GET /category/:id).

Inputs: id (required).

get_category_attributesGet category attributesA
Read-only

Return the attributes for a category (GET /categories/:id/attributes), including input_type, options and whether each is required. These define the attributes you can set when creating a listing in this category.

Inputs: id (required).

get_category_brandsGet category brandsB
Read-only

Return the brands available for a category (GET /categories/:id/brands).

Inputs: id (required).

get_category_childrenGet child categoriesA
Read-only

Return the child categories of a category (GET /categories/:id). Use this to walk the category tree down to a leaf before creating a listing.

Inputs: id (required).

get_category_modelsGet brand modelsA
Read-only

Return the models for a brand within a category (GET /categories/:id/brands/:brand_id/models).

Inputs: id (required), brand_id (required).

get_cityGet city detailA
Read-only

Return a single city with coordinates, zip_code, country_id and canton_id (GET /cities/:id). Use the id as city_id when creating a listing.

Inputs: id (required).

get_listingGet listingA
Read-only

Retrieve a single listing by its id (GET /listings/:id). Returns the full listing object: title, price, location, status, images and owner details.

Inputs: id (required).

get_listing_limitsGet listing limitsA
Read-only

Return per-category listing limits (cars, real-estate, other) with current counts (GET /listing-limits).

Inputs: no named parameters.

get_refresh_limitsGet refresh limitsA
Read-only

Return refresh quota: free_limit, free_count, paid_count, listing_count (GET /listing/refresh/limits).

Inputs: no named parameters.

get_sponsor_priceGet sponsorship price quoteA
Read-only

Get a price quote for sponsoring a listing (GET /listings/:id/sponsore/price). Read-only — ALWAYS call this and show the quote to the user before sponsor_listing.

Inputs: id (required), days (required), type (required), refresh_every (required), +1 more.

get_user_listingsGet a user's listingsA
Read-only

List a user's listings, filtered by state (GET /users/:user/listings and its finished/inactive/expired/hidden variants). Paginated. Use state: active for the public/visible listings. The user is a username for active listings and a user id for the other states, matching the OLX API.

Inputs: user (required), page, state.

hide_listingHide listingA

Hide a listing from search; it stays visible on the user profile (POST /listings/:id/hide).

Inputs: id (required).

list_categoriesList top-level categoriesA
Read-only

Return all top-level categories (GET /categories).

Inputs: no named parameters.

list_citiesList citiesA
Read-only

Return all cities with their cantons (GET /cities).

Inputs: no named parameters.

list_countriesList countriesA
Read-only

Return all countries with id, name and code (GET /countries).

Inputs: no named parameters.

list_country_statesList country states / cantonsB
Read-only

Return country states with their cantons (GET /country-states).

Inputs: no named parameters.

login_statusLogin statusA
Read-only

Force a fresh login with the configured credentials and report success. Useful for diagnosing authentication problems.

Inputs: no named parameters.

publish_listingPublish listingA

Activate a DRAFT listing so it becomes visible in search (POST /listings/:id/publish).

Inputs: id (required).

refresh_listingRefresh listingA

Bump a listing's rank by refreshing its timestamp (PUT /listings/:id/refresh). Subject to quota — check get_refresh_limits. May consume a paid refresh once the free quota is exhausted.

Inputs: id (required).

search_listingsSearch listingsA
Read-only

Full-text search across OLX listings (GET /search). Public — works without credentials. Combine a text query with filters (category, brand, city, price range, condition, recency). Returns a compact summary per listing plus pagination meta and category aggregations. Set raw: true for the full untrimmed payload. Use extra_params for advanced/rare query keys such as attribute filters (attr, attr_encoded) or custom sorting.

Inputs: q, raw, page, state, +10 more.

set_listing_discountSet listing discount (PAID/impactful)A
Destructive

Set a temporary discounted price on a listing (POST /listings/:id/discount). This changes the live price shown to buyers for the given period. Confirm with the user first.

Inputs: id (required), days (required), price (required).

set_main_listing_imageSet main listing imageA

Set a listing's primary/cover image (POST /listings/:id/image-main).

Inputs: id (required), imageId (required).

suggest_categorySuggest category from titleB
Read-only

Suggest categories for a listing title/keyword (GET /categories/suggest?keyword=). Handy for auto-selecting a category when creating a listing.

Inputs: keyword (required).

unhide_listingUnhide listingA

Restore a hidden listing's visibility (POST /listings/:id/unhide).

Inputs: id (required).

update_listingUpdate listingA

Update fields on an existing listing (PUT /listings/:id). Provide only the fields you want to change alongside the listing id.

Inputs: id (required), price, state, title, +11 more.

upload_listing_imageUpload listing image(s)A

Attach image(s) to a listing (POST /listings/:id/image-upload). Provide either image_url (the API fetches it) and/or an images array of image URLs. Returns the created image objects with their ids and sizes.

Inputs: id (required), images, image_url.

whoamiWho am IA
Read-only

Return the currently authenticated OLX user (GET /me). Also confirms that login and token caching are working.

Inputs: no named parameters.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.8/5.0

    Scored across 35 tools

    Disambiguation5/5

    Each tool has a clear, distinct purpose: listing CRUD, images, categories, locations, search, user info, etc. Even with 35 tools, there is no ambiguity; for example, listing lifecycle tools (create, update, publish, finish, hide, etc.) are all uniquely named and described.

    Naming Consistency4/5

    Most tools follow a verb_noun pattern (e.g., get_listing, create_listing, upload_listing_image). Minor inconsistencies: 'whoami' and 'login_status' deviate, and some use different ordering (finish_listing vs. finish_listing_discount). Overall, the pattern is recognizable and predictable.

    Tool Count4/5

    35 tools is on the high side, but they cover a wide range of features for a listing marketplace (CRUD, images, sponsorship, discounts, categories, locations, search). The count is justified by the domain complexity and each tool earns its place.

    Completeness5/5

    The tool surface covers the full listing lifecycle and supporting operations: CRUD, image management, refresh, sponsorship, discounts, limits, categories with attributes and brands, location hierarchy, search, and user authentication. No obvious gaps for the stated purpose of managing OLX listings.

    Maintenance

    ActivityInactive
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • F
      license
      Not graded
      quality
      D
      maintenance
      MCP server for managing OLX.ba / PIK.ba shops, enabling listing management, category/location queries, sponsor operations, and image uploads via natural language.
      -
    • A
      license
      C
      quality
      C
      maintenance
      Exposes every operation from the meloQA v1 API as MCP tools, enabling LLM clients to read and manage meloQA projects, test cases, cycles, executions, bugs, links, and reference data.
      83
      46 npm
      MIT
    • A
      license
      A
      quality
      D
      maintenance
      Exposes the Loyverse API as MCP tools to manage stores, products, inventory, customers, receipts, and more from AI assistants.
      54
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      MCP server for the OLX.ba API that enables searching, publishing, editing, and managing listings (ads), including image handling, sponsorships, categories, locations, and user account operations through 36 tools covering all official API endpoints.
      8 npm
      7
      MIT