Skip to main content
Glama
rezashahnazar

Digikala MCP Server

README.md
# Digikala MCP Server

A Model Context Protocol (MCP) server for intelligent product discovery on Digikala, Iran's largest e-commerce platform.

## 🎯 Key Features

- **Intelligent Discovery Workflow**: Iterative search refinement with query optimization
- **Bilingual Search**: Automatic Persian (Farsi) and English query support
- **Simplified Results**: Returns only marketable products with clean, structured data
- **Smart Ratings**: Star ratings (0-5) only shown when statistically significant (10+ reviews)
- **Comprehensive Tools**: Search, details, recommendations, and AI-powered semantic search

## 💰 Currency Handling

**All price inputs and outputs use TOOMAN currency** (Iranian common currency).

- **User-facing:** All price parameters accept **Toomans**
- **API conversion:** Automatically converts to Rials (1 Tooman = 10 Rials) internally
- **Dual output:** Product prices returned in **both Tooman and Rial** for transparency

**Example:**
```python
# Input: Category ID and keyword (from get_optimized_keywords_and_categories), Price in Toomans
search_products(category_id=22, keyword="laptop", price_min_tooman=5000000, price_max_tooman=20000000)

# Output: Both currencies (simplified, parsed)
{
  "id": 12345,
  "title_fa": "لپ تاپ ایسوس",
  "selling_price_tooman": 1525000,  # 1.525M Toomans
  "selling_price_rial": 15250000,   # 15.25M Rials
  "rating_stars": 4.3,               # Out of 5 (only if 10+ reviews)
  "rating_count": 156
}
```

## 🔍 Discovery Workflow

This server implements an intelligent discovery workflow:

1. **Query Optimization**: Use `get_optimized_keywords_and_categories` with both Persian and English queries
2. **Iterative Search**: Execute `search_products` with category_id and keyword pairs from step 1
3. **Refine Results**: Adjust sorting, pagination, or filters based on results
4. **Deep Dive**: Use `get_product_details` for promising candidates
5. **Expand Search**: Use `get_product_recommendations` for similar products
6. **Visual Search**: Use `search_text_lenz` for clothing/accessories with descriptive queries

## 🛠️ Available Tools

### 1. get_optimized_keywords_and_categories
**Query optimization and category discovery**

- **Purpose**: Get optimized search keywords and relevant category IDs
- **When to use**: ALWAYS call this BEFORE search_products
- **Bilingual**: Call with BOTH Persian (Farsi) and English queries separately
- **Parameters**:
  - `query` (string): Single word query (e.g., 'laptop', 'phone', 'shoe')
- **Returns**: Optimized keywords, category IDs, and codes

**Example:**
```python
# Persian query (single word)
result_fa = get_optimized_keywords_and_categories("لپتاپ")
# English query (single word)
result_en = get_optimized_keywords_and_categories("laptop")

# Returns keyword-category pairs like:
# {"optimized_queries": ["laptop", "gaming laptop"], "categories": [{"id": 22, ...}]}

# Use these keyword-category pairs in search_products
```

---

### 2. search_products
**Core product search with filtering (Uses Search API V2)**

- **Purpose**: Search products within a specific category with advanced filters and sorting
- **Returns**: 20 simplified, marketable products per page
- **Critical**: Call `get_optimized_keywords_and_categories` FIRST to get category_id
- **Required**: Both `category_id` and `keyword` (from step 1 keyword-category pairs)
- **Parameters**:
  - `category_id` (int): **REQUIRED** - Category ID from get_optimized_keywords_and_categories
  - `keyword` (string): **REQUIRED** - Search keyword from get_optimized_keywords_and_categories
  - `page` (int): Page number (default: 1)
  - `sort` (int): Sort order (default: 1)
    - 1: Relevance (default)
    - 2: Price Low to High
    - 3: Price High to Low
    - 4: Newest
    - 5: Best Selling
    - 6: Most Viewed
    - 7: Highest Rated
  - `price_min_tooman` (int): Minimum price in Toomans
  - `price_max_tooman` (int): Maximum price in Toomans
  - `discount_min` (int): Minimum discount %
  - `discount_max` (int): Maximum discount %
  - `colors` (list[int]): Color filter IDs

**Returns**: Simplified product list with:
- `id`, `title_fa`, `title_en`, `url`
- `selling_price_tooman`, `selling_price_rial`
- `rating_stars` (0-5, only if 10+ reviews, otherwise None)
- `rating_count`, `brand`, `category`
- `discount_percent`, `is_incredible`, `is_digiplus_jet_eligible`

---

### 3. get_product_details
**Comprehensive product information**

- **Purpose**: Deep dive into specific products
- **When to use**: After finding promising candidates in search results
- **Parameters**:
  - `product_id` (int): Product ID from search results
- **Returns**: Parsed product details including:
  - Basic info (title, category, brand, URL)
  - Pricing (with Tooman/Rial)
  - Star ratings (0-5, if 10+ reviews)
  - Expert review description
  - Specifications (title, values)
  - Buy suggestion (count, percent)
  - Customer feedback (recommended %, advantages, disadvantages)
  - Available variants and price range

---

### 4. get_product_recommendations
**Similar products and alternatives**

- **Purpose**: Find similar/related products
- **When to use**: When a product is close but not exact match
- **Parameters**:
  - `product_id` (int): Reference product ID
  - `offset` (int, optional): Specific recommendation type
- **Returns**: Simplified product list with:
  - Available recommendation tabs (similar products, related categories)
  - Filtered marketable products only
  - Same fields as search_products

---

### 5. search_text_lenz
**AI-powered semantic search**

- **Purpose**: Visual/descriptive product search
- **Best for**: Clothing, accessories, wearables, shoes
- **Query format**: 2-3 word descriptions (e.g., "red summer dress", "black running shoes")
- **Parameters**:
  - `query` (string): Visual/descriptive query
  - `page` (int): Page number (default: 1)
- **Returns**: Simplified product list plus:
  - `is_text_lenz_eligible`: Whether Text-Lenz was used
  - `related_searches`: Alternative search suggestions
  - Pagination metadata

## Installation

```bash
# Install dependencies
uv sync

# Or add to existing project
uv add "mcp[cli]" httpx
```

## Usage

### Running the Server

#### STDIO Transport (for Claude Desktop, Cursor, etc.)
```bash
uv run python main.py
```

#### Testing with MCP Inspector
```bash
uv run mcp dev main.py
```

### Integration with Claude Desktop

Add to your Claude Desktop configuration (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):

```json
{
  "mcpServers": {
    "digikala": {
      "command": "/path/to/local/uv",
      "args": [
          "run",
          "--directory",
          "/path/to/digikala-mcp-server",
          "python",
          "main.py"
        ]
    }
  }
}
```

## 📋 Example Usage

### Example 1: Complete Discovery Workflow
```
Find me the best gaming laptop under 50M Toomans
```

**AI Agent Workflow:**
1. Call `get_optimized_keywords_and_categories("لپتاپ")` (Farsi - single word)
2. Call `get_optimized_keywords_and_categories("laptop")` (English - single word)
3. Use keyword-category pairs from step 1 in `search_products`:
   - Example: `search_products(category_id=22, keyword="gaming laptop", price_max_tooman=50000000, sort=7)`
   - Try multiple keywords: "laptop", "gaming laptop", etc. with same category_id
   - Set `sort=7` (Highest Rated) or `sort=5` (Best Selling)
4. Review results, maybe try `sort=3` (Price High to Low) for premium options
5. Call `get_product_details(product_id)` for top 3 candidates
6. Compare specifications, ratings, and customer feedback

---

### Example 2: Iterative Search Refinement
```
I want noise-cancelling headphones for under 10M Toomans
```

**AI Agent Workflow:**
1. Optimize: `get_optimized_keywords_and_categories("هدفون")` (single word)
2. Optimize: `get_optimized_keywords_and_categories("headphone")` (single word)
3. Get keyword-category pairs and search:
   - `search_products(category_id=83, keyword="noise cancelling headphones", price_max_tooman=10000000)`
4. If too many results: Add `sort=7` (Highest Rated)
5. If too few results: Try different keywords or `sort=5` (Best Selling) or increase price
6. Review page 2-3 if needed with `page=2`
7. Get details for promising products

---

### Example 3: Visual/Descriptive Search
```
Find me a casual blue shirt for summer
```

**AI Agent Workflow:**
1. Use `search_text_lenz("blue casual shirt")` - exceptional for clothing
2. Review results and related searches
3. Try variations: `search_text_lenz("summer blue shirt")`
4. Get details for promising items
5. Use `get_product_recommendations` to explore similar styles

---

### Example 4: Finding Alternatives
```
I like this product but want to see similar options
```

**AI Agent Workflow:**
1. Get current product: `get_product_details(product_id)`
2. Get alternatives: `get_product_recommendations(product_id)`
3. Review available recommendation tabs
4. Try different offsets for category neighbors
5. Get details for interesting alternatives

## Development

### Project Structure
```
digikala-mcp-server/
├── main.py              # MCP server implementation
├── tests.py             # Comprehensive test suite
├── pyproject.toml       # Project configuration
├── uv.lock             # Dependency lock file
└── README.md           # This file
```

### Development Approach

This project follows a diffusion-inspired iterative development methodology:
- Phase 1: Simple working core (query optimization + basic search)
- Phase 2: Enhanced features (simplified outputs, bilingual support, integrated extraction)
- Phase 3: Smart filtering (marketable products, star ratings, intelligent defaults)
- Future: Error handling and production hardening

### Key Design Decisions

1. **Simplified Outputs**: All tools return parsed, clean data instead of raw API responses
2. **Marketable Products Only**: Non-available products are filtered out automatically
3. **Smart Ratings**: Star ratings (0-5) only shown when statistically significant (10+ reviews)
4. **Bilingual Support**: Emphasis on searching with both Persian and English queries
5. **Integrated Extraction**: Product extraction built into search tools, not separate
6. **Intelligent Defaults**: Always filters for available stock (has_selling_stock=1)

### Testing

#### Comprehensive Test Suite

Run the full test suite covering all refactored tools:

```bash
uv run python tests.py
```

The test suite validates:
- ✅ Query optimization (bilingual support)
- ✅ Simplified search results (marketable products only)
- ✅ Rating conversion (stars from 0-5)
- ✅ Pagination (20 items per page)
- ✅ Filtering and sorting
- ✅ Parsed product details
- ✅ Simplified recommendations
- ✅ Text-Lenz semantic search
- ✅ Currency conversion (Tooman/Rial)
- ✅ Edge cases and error handling

**Features:**
- Built-in timeout protection (30s per HTTP request)
- Proper error handling and cleanup
- Validates all tool outputs are simplified/parsed
- Exit codes for CI/CD integration

#### Direct Function Testing

Quick testing of individual functions:

```python
from main import get_optimized_keywords_and_categories, search_products, get_product_details

# Test query optimization (single word queries)
optimized = get_optimized_keywords_and_categories("لپتاپ")
print(f"Optimized keywords: {optimized['optimized_queries']}")
print(f"Categories: {optimized['categories']}")

# Extract keyword-category pair
category_id = optimized['categories'][0]['id']  # e.g., 22
keyword = optimized['categories'][0]['query']   # e.g., "laptop"

# Test search with filters (returns simplified products directly)
results = search_products(
    category_id=category_id,  # REQUIRED - from optimization step
    keyword=keyword,          # REQUIRED - from optimization step
    price_min_tooman=1000000,   # 10M Rials
    price_max_tooman=10000000,  # 100M Rials
    sort=2,  # Price Low to High
)

# Results are already simplified
for product in results['products'][:3]:
    rating = f"{product['rating_stars']}⭐" if product['rating_stars'] else "No rating"
    print(f"{product['title_fa']}: {product['selling_price_tooman']:,} Toomans - {rating}")

# Get detailed info
details = get_product_details(results['products'][0]['id'])
print(f"Specs: {len(details['specifications'])} attributes")
print(f"Customer feedback: {details.get('customer_feedback', {})}")
```

## API Documentation

This server integrates with:
- Digikala Autocomplete API v1: `https://api.digikala.com/v1/autocomplete/`
- Digikala Search API v2: `https://api.digikala.com/v2/category/{category_id}/`
- Digikala Product Details API v2: `https://api.digikala.com/v2/product/{id}/`
- Digikala Tabular Recommendations API v1: `https://api.digikala.com/v1/product/{id}/tabular-recommendation/`
- Digikala Text-Lenz Search API v1: `https://api.digikala.com/v1/search/text-lenz/`

## License

MIT

## 📊 Product Data Format

All tools return products in this simplified format:

```python
{
    "id": 12345,
    "title_fa": "عنوان فارسی محصول",
    "title_en": "Product English Title",
    "url": "/product/dkp-12345/...",
    "selling_price_rial": 15250000,
    "selling_price_tooman": 1525000,
    "rrp_price_rial": 18000000,
    "rrp_price_tooman": 1800000,
    "discount_percent": 15,
    "rating_stars": 4.3,        # 0-5 scale, None if <10 reviews
    "rating_count": 156,
    "brand": "Samsung",
    "category": "[Mobile,موبایل]",
    "is_incredible": False,
    "is_digiplus_jet_eligible": True
}
```

**Notes:**
- Only **marketable** products are returned (automatically filtered)
- `rating_stars` is `None` if `rating_count < 10` (not statistically significant)
- Both Tooman and Rial prices always included
- URL relative to digikala.com

---

## Version

0.2.0 - Refactored with simplified outputs and intelligent discovery workflow
- Integrated extraction into search tools
- Bilingual search support
- Smart rating conversion
- Parsed/simplified all outputs
- Intelligent filtering defaults

TDQS

A4.3/5.0

Scored across 5 tools

Disambiguation4/5

The tools have mostly distinct purposes, with clear boundaries: get_optimized_keywords_and_categories for keyword/category optimization, get_product_details for detailed product info, get_product_recommendations for similar products, search_products for category-based searches, and search_text_lenz for semantic visual searches. However, search_products and search_text_lenz both involve searching, which could cause minor confusion, though their descriptions clarify different use cases (category-based vs. semantic/visual).

Naming Consistency4/5

Tool names follow a consistent verb_noun pattern with underscores (e.g., get_optimized_keywords_and_categories, search_products), making them predictable and readable. There is a minor deviation with search_text_lenz, which includes a brand name 'Text-Lenz' in the noun part, but it still fits the overall naming convention without mixing styles like camelCase.

Tool Count5/5

With 5 tools, this server is well-scoped for an e-commerce product search and information domain. Each tool serves a specific function (e.g., optimization, details, recommendations, searches), and none feel redundant or unnecessary, providing a balanced set for typical agent workflows in this context.

Completeness3/5

The tool set covers key operations like searching, getting details, and recommendations, but there are notable gaps. For example, there are no tools for user account management (e.g., login, cart operations), purchase-related actions (e.g., add to cart, checkout), or content management (e.g., reviews, ratings). While the domain appears focused on product discovery and information, these omissions could limit agent functionality in full e-commerce scenarios.

Maintenance

ActivityInactive
ResponsivenessNo issues