hepsiburada-mcp 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,20 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags: ["v*"]
6
+
7
+ jobs:
8
+ publish:
9
+ runs-on: ubuntu-latest
10
+ permissions:
11
+ id-token: write # required for PyPI trusted publishing (OIDC)
12
+ contents: read
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ - uses: actions/setup-python@v5
16
+ with:
17
+ python-version: "3.12"
18
+ - run: pip install build
19
+ - run: python -m build
20
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,61 @@
1
+ name: Publish to MCP Registry
2
+
3
+ # Official MCP Registry (registry.modelcontextprotocol.io) via GitHub OIDC.
4
+ # No secret, no interactive login: the runner's OIDC token proves ownership
5
+ # of the io.github.mohammad-abbasi-sh/* namespace.
6
+ # Refs: https://github.com/modelcontextprotocol/registry
7
+
8
+ on:
9
+ push:
10
+ tags: ["v*"]
11
+ workflow_dispatch:
12
+
13
+ jobs:
14
+ publish:
15
+ runs-on: ubuntu-latest
16
+ permissions:
17
+ id-token: write # required for OIDC -> MCP Registry
18
+ contents: read
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+
22
+ - name: Sync server.json version to tag
23
+ # Only sync when running on a version tag (v*). On workflow_dispatch
24
+ # (ref = refs/heads/main) keep the version committed in server.json.
25
+ run: |
26
+ VER=""
27
+ if [[ "$GITHUB_REF" == refs/tags/* ]]; then
28
+ TAG="${GITHUB_REF#refs/tags/}"
29
+ VER="${TAG#v}"
30
+ fi
31
+ if [ -n "$VER" ]; then
32
+ python3 - "$VER" << 'EOF'
33
+ import json, sys
34
+ ver = sys.argv[1]
35
+ d = json.load(open('server.json'))
36
+ d['version'] = ver
37
+ for pkg in d.get('packages', []):
38
+ pkg['version'] = ver
39
+ json.dump(d, open('server.json', 'w'), indent=2, ensure_ascii=False)
40
+ print('server.json version ->', ver)
41
+ EOF
42
+ else
43
+ echo "No version tag ($GITHUB_REF); keeping server.json version as-is"
44
+ fi
45
+
46
+ - name: Install mcp-publisher
47
+ run: |
48
+ curl -sL "https://github.com/modelcontextprotocol/registry/releases/download/v1.8.7/mcp-publisher_linux_amd64.tar.gz" -o /tmp/mcp-publisher.tar.gz
49
+ tar -xzf /tmp/mcp-publisher.tar.gz -C /tmp
50
+ sudo mv /tmp/mcp-publisher /usr/local/bin/mcp-publisher
51
+ mcp-publisher --version
52
+
53
+ - name: Validate server.json
54
+ run: mcp-publisher validate server.json
55
+
56
+ - name: Publish to MCP Registry (OIDC)
57
+ run: |
58
+ mcp-publisher login github-oidc
59
+ mcp-publisher publish server.json
60
+ # A registry outage must never break the release; re-run from Actions if needed.
61
+ continue-on-error: true
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mohammad Abbasi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,113 @@
1
+ Metadata-Version: 2.5
2
+ Name: hepsiburada-mcp
3
+ Version: 0.1.0
4
+ Summary: Unofficial read-only MCP server for hepsiburada.com shopping (search, product details, reviews, categories, price stats)
5
+ Author: Mohammad Abbasi
6
+ License: MIT
7
+ License-File: LICENSE
8
+ Requires-Python: >=3.10
9
+ Requires-Dist: curl-cffi>=0.7
10
+ Requires-Dist: mcp<2
11
+ Description-Content-Type: text/markdown
12
+
13
+ # hepsiburada-mcp 🇹🇷
14
+
15
+ mcp-name: io.github.mohammad-abbasi-sh/hepsiburada-mcp
16
+
17
+ Unofficial **read-only** MCP server for **hepsiburada.com**, Türkiye's leading e-commerce marketplace — search millions of products, read product details (price, stock, seller, GTIN, highlights), read customer reviews, browse the 9 top categories, and get price statistics (min / median / mean / max) for any query.
18
+
19
+ > Built by Mohammad Abbasi as part of the "Turkey MCP factory" (Sepehr-style pipeline). Not affiliated with hepsiburada.com.
20
+
21
+ ## For AI agents
22
+
23
+ Add to your MCP client config (stdio):
24
+
25
+ ```json
26
+ {
27
+ "mcpServers": {
28
+ "hepsiburada": {
29
+ "command": "uvx",
30
+ "args": ["hepsiburada-mcp"]
31
+ }
32
+ }
33
+ }
34
+ ```
35
+
36
+ Or run locally: `python -m hepsiburada_mcp.server` (needs `mcp<2`, `curl-cffi`).
37
+
38
+ ## Tools
39
+
40
+ | Tool | Description |
41
+ |------|-------------|
42
+ | `hepsiburada_search` | Search products by keyword — `query` ("iphone", "kablosuz kulaklık"), `sort` ("relevance" / "price_asc" / "price_desc"), `limit` 1..24, `page` 1-based; returns title, price in TRY, rating, review count, URL, SKU, image, campaign |
43
+ | `hepsiburada_product_detail` | Detail of one product (`product` = full URL or path with "-p-HBCV…"): name, brand, price in TRY, stock status, rating, review count, seller (+ official-seller flag), category path, color, GTIN, images, highlights |
44
+ | `hepsiburada_list_categories` | The 9 top categories: Turkish name, URL, category id |
45
+ | `hepsiburada_price_stats` | Price statistics for a query: count, min / median / mean / max price in TRY across the first page |
46
+ | `hepsiburada_product_reviews` | Recent customer reviews of one product: author, star rating, review text, date |
47
+
48
+ Example output (`hepsiburada_search` / "iphone"):
49
+
50
+ ```json
51
+ {"query": "iphone", "sort": "relevance", "page": 1, "count": 3, "products": [
52
+ {"title": "Apple iPhone 15 128 GB Mavi",
53
+ "url": "https://www.hepsiburada.com/apple-iphone-15-128-gb-mavi-p-HBCV00004X9ZCK",
54
+ "sku": "HBCV00004X9ZCK", "price_try": 56999.0, "rating": 4.8,
55
+ "review_count": 13102, "campaign": "30 günün en düşük fiyatı"}, …]}
56
+ ```
57
+
58
+ Example output (`hepsiburada_product_detail` / iPhone 15):
59
+
60
+ ```json
61
+ {"name": "Apple iPhone 15 128 GB", "sku": "HBCV00004X9ZCK", "brand": "Apple",
62
+ "category": "Telefon > Cep Telefonu > iPhone iOS Telefonlar", "color": "Mavi",
63
+ "gtin": "0195949036583", "price_try": 56999.0, "price_currency": "TRY",
64
+ "in_stock": true, "rating": 4.8, "review_count": 13102,
65
+ "seller": "Hepsiburada", "official_seller": true,
66
+ "highlights": ["Ekran : 6.1 inç Super Retina XDR OLED, …"], …}
67
+ ```
68
+
69
+ Example output (`hepsiburada_price_stats` / "iphone"):
70
+
71
+ ```json
72
+ {"query": "iphone", "sort": "relevance", "count": 3, "min_try": 56999.0,
73
+ "median_try": 102999.0, "mean_try": 91115.67, "max_try": 113349.0}
74
+ ```
75
+
76
+ ## How it works
77
+
78
+ hepsiburada.com returns HTTP 403 to plain HTTP clients, so the transport
79
+ uses Chrome TLS impersonation (`curl-cffi`, `chrome120`). There is no public
80
+ JSON API — data comes from the site's server-rendered HTML: search pages
81
+ carry product cards, product pages carry schema.org Product JSON-LD plus a
82
+ seller block and a "Ürün Özellikleri" highlights list, and the homepage
83
+ carries the top categories. Requests are spaced ~0.8s apart; everything is
84
+ read-only, no login, no API key.
85
+
86
+ ## Install
87
+
88
+ ```bash
89
+ uvx hepsiburada-mcp # run directly (needs uv)
90
+ # or
91
+ pip install hepsiburada-mcp
92
+ hepsiburada-mcp # starts the MCP server on stdio
93
+ ```
94
+
95
+ ## Tests
96
+
97
+ ```bash
98
+ python -m venv .venv && .venv/bin/pip install -e .
99
+ .venv/bin/python -m unittest discover -s tests -v
100
+ ```
101
+
102
+ Offline tests run on recorded fixtures (real pages fetched 2026-11-06);
103
+ live tests hit hepsiburada.com.
104
+
105
+ ## Roadmap
106
+
107
+ - Category-scoped search (search within one `-c-…` category)
108
+ - Seller store pages (other sellers of the same product)
109
+ - Price history (track a SKU over days)
110
+
111
+ ## License
112
+
113
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,83 @@
1
+ # hepsiburada-mcp 🇹🇷
2
+
3
+ mcp-name: io.github.mohammad-abbasi-sh/hepsiburada-mcp
4
+
5
+ سرور MCP غیررسمی و **فقط‌خواندنی** برای **hepsiburada.com**، بزرگ‌ترین
6
+ فروشگاه اینترنتی ترکیه — جست‌وجو در میلیون‌ها کالا، خواندن جزئیات کالا
7
+ (قیمت، موجودی، فروشنده، GTIN، ویژگی‌های برجسته)، خواندن نظرهای مشتریان،
8
+ مرور ۹ دسته‌ی اصلی، و گرفتن آمار قیمت (کمترین / میانه / میانگین /
9
+ بیشترین) برای هر جست‌وجو.
10
+
11
+ > ساخته‌ی محمد عباسی در چارچوب «کارخانه‌ی MCP ترکیه» (به سبک سپهر). هیچ
12
+ > وابستگی‌ای به hepsiburada.com ندارد.
13
+
14
+ ## برای ایجنت‌های هوش مصنوعی
15
+
16
+ به پیکربندی MCP client خود اضافه کنید (stdio):
17
+
18
+ ```json
19
+ {
20
+ "mcpServers": {
21
+ "hepsiburada": {
22
+ "command": "uvx",
23
+ "args": ["hepsiburada-mcp"]
24
+ }
25
+ }
26
+ }
27
+ ```
28
+
29
+ یا به‌صورت محلی اجرا کنید: `python -m hepsiburada_mcp.server`
30
+ (نیازمند `mcp<2` و `curl-cffi`).
31
+
32
+ ## ابزارها
33
+
34
+ | ابزار | توضیح |
35
+ |------|-------|
36
+ | `hepsiburada_search` | جست‌وجوی کالا با کلیدواژه — `query` (مثل «iphone» یا «kablosuz kulaklık»)، `sort` (‏«relevance» / ‏«price_asc» / ‏«price_desc»)، `limit` از ۱ تا ۲۴، `page` از ۱؛ برمی‌گرداند: عنوان، قیمت به لیر، امتیاز، تعداد نظر، آدرس، SKU، عکس، کمپین |
37
+ | `hepsiburada_product_detail` | جزئیات یک کالا (`product` = آدرس کامل یا مسیر حاوی «-p-HBCV…»): نام، برند، قیمت به لیر، وضعیت موجودی، امتیاز، تعداد نظر، فروشنده (+ فروشنده‌ی رسمی)، مسیر دسته، رنگ، GTIN، عکس‌ها، ویژگی‌های برجسته |
38
+ | `hepsiburada_list_categories` | ۹ دسته‌ی اصلی: نام ترکی، آدرس، شناسه‌ی دسته |
39
+ | `hepsiburada_price_stats` | آمار قیمت برای یک جست‌وجو: تعداد، کمترین / میانه / میانگین / بیشترین قیمت (لیر) |
40
+ | `hepsiburada_product_reviews` | نظرهای اخیر مشتریان برای یک کالا: نویسنده، امتیاز ستاره‌ای، متن نظر، تاریخ |
41
+
42
+ نمونه‌ی خروجی (`hepsiburada_search` / ‏«iphone»):
43
+
44
+ ```json
45
+ {"query": "iphone", "count": 3, "products": [
46
+ {"title": "Apple iPhone 15 128 GB Mavi",
47
+ "url": "https://www.hepsiburada.com/apple-iphone-15-128-gb-mavi-p-HBCV00004X9ZCK",
48
+ "sku": "HBCV00004X9ZCK", "price_try": 56999.0, "rating": 4.8,
49
+ "review_count": 13102}, …]}
50
+ ```
51
+
52
+ ## چطور کار می‌کند؟
53
+
54
+ سایت hepsiburada.com به کلاینت‌های HTTP ساده خطای 403 می‌دهد؛ به همین
55
+ دلیل لایه‌ی انتقال از جعل TLS کروم (`curl-cffi`، ‏`chrome120`) استفاده
56
+ می‌کند. API عمومی JSON ندارد — داده‌ها از HTML رندرشده‌ی سمت سرور
57
+ می‌آیند: صفحه‌های جست‌وجو کارت‌های کالا دارند، صفحه‌های کالا JSON-LD از
58
+ نوع Product به‌همراه بلوک فروشنده و فهرست «Ürün Özellikleri»، و صفحه‌ی
59
+ اصلی دسته‌های اصلی را دارد. درخواست‌ها با فاصله‌ی حدود ۰٫۸ ثانیه
60
+ فرستاده می‌شوند؛ همه‌چیز فقط‌خواندنی است، بدون لاگین و بدون کلید API.
61
+
62
+ ## نصب
63
+
64
+ ```bash
65
+ uvx hepsiburada-mcp # اجرای مستقیم (نیازمند uv)
66
+ # یا
67
+ pip install hepsiburada-mcp
68
+ hepsiburada-mcp # اجرای سرور MCP روی stdio
69
+ ```
70
+
71
+ ## تست‌ها
72
+
73
+ ```bash
74
+ python -m venv .venv && .venv/bin/pip install -e .
75
+ .venv/bin/python -m unittest discover -s tests -v
76
+ ```
77
+
78
+ تست‌های آفلاین روی نمونه‌های ضبط‌شده از صفحه‌های واقعی اجرا می‌شوند
79
+ (دریافت‌شده در ۲۰۲۶-۱۱-۰۶)؛ تست‌های زنده به hepsiburada.com وصل می‌شوند.
80
+
81
+ ## لایسنس
82
+
83
+ MIT — ببینید [LICENSE](LICENSE).
@@ -0,0 +1,83 @@
1
+ # hepsiburada-mcp 🇹🇷
2
+
3
+ mcp-name: io.github.mohammad-abbasi-sh/hepsiburada-mcp
4
+
5
+ Türkiye'nin önde gelen e-ticaret pazaryeri **hepsiburada.com** için resmi
6
+ olmayan, **salt okunur** MCP sunucusu — milyonlarca üründe arama yapın,
7
+ ürün detaylarını okuyun (fiyat, stok, satıcı, GTIN, öne çıkan özellikler),
8
+ müşteri yorumlarını okuyun, 9 ana kategoriye göz atın ve herhangi bir
9
+ sorgu için fiyat istatistikleri (min / medyan / ortalama / maks) alın.
10
+
11
+ > Mohammad Abbasi tarafından "Turkey MCP factory" (Sepehr tarzı süreç)
12
+ > kapsamında geliştirildi. hepsiburada.com ile bağlantısı yoktur.
13
+
14
+ ## Yapay zekâ ajanları için
15
+
16
+ MCP istemci yapılandırmanıza ekleyin (stdio):
17
+
18
+ ```json
19
+ {
20
+ "mcpServers": {
21
+ "hepsiburada": {
22
+ "command": "uvx",
23
+ "args": ["hepsiburada-mcp"]
24
+ }
25
+ }
26
+ }
27
+ ```
28
+
29
+ veya yerel çalıştırın: `python -m hepsiburada_mcp.server`
30
+ (`mcp<2`, `curl-cffi` gerekir).
31
+
32
+ ## Araçlar
33
+
34
+ | Araç | Açıklama |
35
+ |------|----------|
36
+ | `hepsiburada_search` | Anahtar kelimeyle ürün arama — `query` ("iphone", "kablosuz kulaklık"), `sort` ("relevance" / "price_asc" / "price_desc"), `limit` 1..24, `page` 1'den başlar; başlık, TL fiyat, puan, yorum sayısı, URL, SKU, görsel, kampanya döndürür |
37
+ | `hepsiburada_product_detail` | Bir ürünün detayı (`product` = "-p-HBCV…" içeren URL veya yol): ad, marka, TL fiyat, stok durumu, puan, yorum sayısı, satıcı (+ resmi satıcı işareti), kategori yolu, renk, GTIN, görseller, öne çıkanlar |
38
+ | `hepsiburada_list_categories` | 9 ana kategori: Türkçe ad, URL, kategori kimliği |
39
+ | `hepsiburada_price_stats` | Bir sorgunun fiyat istatistikleri: adet, min / medyan / ortalama / maks fiyat (TL) |
40
+ | `hepsiburada_product_reviews` | Bir ürünün son müşteri yorumları: yazar, yıldız puanı, yorum metni, tarih |
41
+
42
+ Örnek çıktı (`hepsiburada_search` / "iphone"):
43
+
44
+ ```json
45
+ {"query": "iphone", "count": 3, "products": [
46
+ {"title": "Apple iPhone 15 128 GB Mavi",
47
+ "url": "https://www.hepsiburada.com/apple-iphone-15-128-gb-mavi-p-HBCV00004X9ZCK",
48
+ "sku": "HBCV00004X9ZCK", "price_try": 56999.0, "rating": 4.8,
49
+ "review_count": 13102}, …]}
50
+ ```
51
+
52
+ ## Nasıl çalışır?
53
+
54
+ hepsiburada.com düz HTTP istemcilerine HTTP 403 döndürür; bu yüzden
55
+ aktarım Chrome TLS taklidi (`curl-cffi`, `chrome120`) kullanır. Herkese
56
+ açık bir JSON API yoktur — veriler sitenin sunucu taraflı işlenmiş
57
+ HTML sayfalarından gelir: arama sayfaları ürün kartları, ürün sayfaları
58
+ schema.org Product JSON-LD + satıcı bloğu + "Ürün Özellikleri" listesi,
59
+ ana sayfa ise ana kategorileri taşır. İstekler ~0.8 sn arayla yapılır;
60
+ her şey salt okunurdur, giriş gerekmez, API anahtarı gerekmez.
61
+
62
+ ## Kurulum
63
+
64
+ ```bash
65
+ uvx hepsiburada-mcp # doğrudan çalıştır (uv gerekir)
66
+ # veya
67
+ pip install hepsiburada-mcp
68
+ hepsiburada-mcp # MCP sunucusunu stdio üzerinde başlatır
69
+ ```
70
+
71
+ ## Testler
72
+
73
+ ```bash
74
+ python -m venv .venv && .venv/bin/pip install -e .
75
+ .venv/bin/python -m unittest discover -s tests -v
76
+ ```
77
+
78
+ Çevrimdışı testler kayıtlı örnek sayfalarla çalışır (gerçek sayfalar,
79
+ 2026-11-06); canlı testler hepsiburada.com'a bağlanır.
80
+
81
+ ## Lisans
82
+
83
+ MIT — bkz. [LICENSE](LICENSE).
@@ -0,0 +1,101 @@
1
+ # hepsiburada-mcp 🇹🇷
2
+
3
+ mcp-name: io.github.mohammad-abbasi-sh/hepsiburada-mcp
4
+
5
+ Unofficial **read-only** MCP server for **hepsiburada.com**, Türkiye's leading e-commerce marketplace — search millions of products, read product details (price, stock, seller, GTIN, highlights), read customer reviews, browse the 9 top categories, and get price statistics (min / median / mean / max) for any query.
6
+
7
+ > Built by Mohammad Abbasi as part of the "Turkey MCP factory" (Sepehr-style pipeline). Not affiliated with hepsiburada.com.
8
+
9
+ ## For AI agents
10
+
11
+ Add to your MCP client config (stdio):
12
+
13
+ ```json
14
+ {
15
+ "mcpServers": {
16
+ "hepsiburada": {
17
+ "command": "uvx",
18
+ "args": ["hepsiburada-mcp"]
19
+ }
20
+ }
21
+ }
22
+ ```
23
+
24
+ Or run locally: `python -m hepsiburada_mcp.server` (needs `mcp<2`, `curl-cffi`).
25
+
26
+ ## Tools
27
+
28
+ | Tool | Description |
29
+ |------|-------------|
30
+ | `hepsiburada_search` | Search products by keyword — `query` ("iphone", "kablosuz kulaklık"), `sort` ("relevance" / "price_asc" / "price_desc"), `limit` 1..24, `page` 1-based; returns title, price in TRY, rating, review count, URL, SKU, image, campaign |
31
+ | `hepsiburada_product_detail` | Detail of one product (`product` = full URL or path with "-p-HBCV…"): name, brand, price in TRY, stock status, rating, review count, seller (+ official-seller flag), category path, color, GTIN, images, highlights |
32
+ | `hepsiburada_list_categories` | The 9 top categories: Turkish name, URL, category id |
33
+ | `hepsiburada_price_stats` | Price statistics for a query: count, min / median / mean / max price in TRY across the first page |
34
+ | `hepsiburada_product_reviews` | Recent customer reviews of one product: author, star rating, review text, date |
35
+
36
+ Example output (`hepsiburada_search` / "iphone"):
37
+
38
+ ```json
39
+ {"query": "iphone", "sort": "relevance", "page": 1, "count": 3, "products": [
40
+ {"title": "Apple iPhone 15 128 GB Mavi",
41
+ "url": "https://www.hepsiburada.com/apple-iphone-15-128-gb-mavi-p-HBCV00004X9ZCK",
42
+ "sku": "HBCV00004X9ZCK", "price_try": 56999.0, "rating": 4.8,
43
+ "review_count": 13102, "campaign": "30 günün en düşük fiyatı"}, …]}
44
+ ```
45
+
46
+ Example output (`hepsiburada_product_detail` / iPhone 15):
47
+
48
+ ```json
49
+ {"name": "Apple iPhone 15 128 GB", "sku": "HBCV00004X9ZCK", "brand": "Apple",
50
+ "category": "Telefon > Cep Telefonu > iPhone iOS Telefonlar", "color": "Mavi",
51
+ "gtin": "0195949036583", "price_try": 56999.0, "price_currency": "TRY",
52
+ "in_stock": true, "rating": 4.8, "review_count": 13102,
53
+ "seller": "Hepsiburada", "official_seller": true,
54
+ "highlights": ["Ekran : 6.1 inç Super Retina XDR OLED, …"], …}
55
+ ```
56
+
57
+ Example output (`hepsiburada_price_stats` / "iphone"):
58
+
59
+ ```json
60
+ {"query": "iphone", "sort": "relevance", "count": 3, "min_try": 56999.0,
61
+ "median_try": 102999.0, "mean_try": 91115.67, "max_try": 113349.0}
62
+ ```
63
+
64
+ ## How it works
65
+
66
+ hepsiburada.com returns HTTP 403 to plain HTTP clients, so the transport
67
+ uses Chrome TLS impersonation (`curl-cffi`, `chrome120`). There is no public
68
+ JSON API — data comes from the site's server-rendered HTML: search pages
69
+ carry product cards, product pages carry schema.org Product JSON-LD plus a
70
+ seller block and a "Ürün Özellikleri" highlights list, and the homepage
71
+ carries the top categories. Requests are spaced ~0.8s apart; everything is
72
+ read-only, no login, no API key.
73
+
74
+ ## Install
75
+
76
+ ```bash
77
+ uvx hepsiburada-mcp # run directly (needs uv)
78
+ # or
79
+ pip install hepsiburada-mcp
80
+ hepsiburada-mcp # starts the MCP server on stdio
81
+ ```
82
+
83
+ ## Tests
84
+
85
+ ```bash
86
+ python -m venv .venv && .venv/bin/pip install -e .
87
+ .venv/bin/python -m unittest discover -s tests -v
88
+ ```
89
+
90
+ Offline tests run on recorded fixtures (real pages fetched 2026-11-06);
91
+ live tests hit hepsiburada.com.
92
+
93
+ ## Roadmap
94
+
95
+ - Category-scoped search (search within one `-c-…` category)
96
+ - Seller store pages (other sellers of the same product)
97
+ - Price history (track a SKU over days)
98
+
99
+ ## License
100
+
101
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,22 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "hepsiburada-mcp"
7
+ version = "0.1.0"
8
+ description = "Unofficial read-only MCP server for hepsiburada.com shopping (search, product details, reviews, categories, price stats)"
9
+ readme = "README.md"
10
+ license = { text = "MIT" }
11
+ requires-python = ">=3.10"
12
+ dependencies = [
13
+ "mcp<2",
14
+ "curl-cffi>=0.7",
15
+ ]
16
+ authors = [{ name = "Mohammad Abbasi" }]
17
+
18
+ [project.scripts]
19
+ hepsiburada-mcp = "hepsiburada_mcp.server:main"
20
+
21
+ [tool.hatch.build.targets.wheel]
22
+ packages = ["src/hepsiburada_mcp"]
@@ -0,0 +1 @@
1
+ {"$schema":"https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json","description":"Unofficial read-only MCP server for hepsiburada.com shopping: search, details, reviews, prices.","name":"io.github.mohammad-abbasi-sh/hepsiburada-mcp","packages":[{"identifier":"hepsiburada-mcp","registryBaseUrl":"https://pypi.org","registryType":"pypi","transport":{"type":"stdio"},"version":"0.1.0"}],"repository":{"source":"github","url":"https://github.com/mohammad-abbasi-sh/hepsiburada-mcp"},"title":"hepsiburada.com Shopping","version":"0.1.0","websiteUrl":"https://github.com/mohammad-abbasi-sh/hepsiburada-mcp"}
@@ -0,0 +1 @@
1
+ """hepsiburada_mcp — unofficial read-only MCP server for hepsiburada.com."""
@@ -0,0 +1,88 @@
1
+ """HTTP layer for hepsiburada_mcp — Chrome TLS impersonation required.
2
+
3
+ hepsiburada.com returns HTTP 403 to plain curl/httpx with a browser UA
4
+ (verified live 2026-11-06: 403 on homepage AND search with plain curl),
5
+ but answers HTTP 200 to curl-cffi chrome120 impersonation. There is no
6
+ public JSON API and no login involved — the site is server-rendered HTML,
7
+ so the transport must impersonate a real browser at the TLS level.
8
+ Requests are kept gentle (one at a time, ~0.8s apart) and read-only.
9
+ """
10
+ from __future__ import annotations
11
+
12
+ import time
13
+ from urllib.parse import quote_plus, urlparse
14
+
15
+ from curl_cffi import requests as _r
16
+
17
+ BASE = "https://www.hepsiburada.com"
18
+ TIMEOUT = 30.0
19
+ MIN_INTERVAL = 0.8 # seconds between requests — be polite
20
+
21
+ _HEADERS = {
22
+ "Accept-Language": "tr-TR,tr;q=0.9,en;q=0.8",
23
+ "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
24
+ }
25
+
26
+ _last_fetch = 0.0
27
+
28
+
29
+ class HepsiburadaError(RuntimeError):
30
+ pass
31
+
32
+
33
+ def _get(url: str) -> str:
34
+ global _last_fetch
35
+ wait = MIN_INTERVAL - (time.monotonic() - _last_fetch)
36
+ if wait > 0:
37
+ time.sleep(wait)
38
+ try:
39
+ resp = _r.get(url, impersonate="chrome120", headers=_HEADERS, timeout=TIMEOUT)
40
+ except Exception as e:
41
+ raise HepsiburadaError(f"network error fetching {url}: {e}") from e
42
+ finally:
43
+ _last_fetch = time.monotonic()
44
+ if resp.status_code == 403:
45
+ raise HepsiburadaError(
46
+ "hepsiburada.com refused the request (HTTP 403, bot wall) — try again later"
47
+ )
48
+ if resp.status_code == 429:
49
+ raise HepsiburadaError(
50
+ "hepsiburada.com rate-limited the request (HTTP 429) — try again later"
51
+ )
52
+ if resp.status_code == 404:
53
+ raise HepsiburadaError(f"page not found (HTTP 404): {url}")
54
+ if resp.status_code != 200:
55
+ raise HepsiburadaError(f"unexpected HTTP {resp.status_code} fetching {url}")
56
+ return resp.text
57
+
58
+
59
+ def fetch_search_html(query: str, sort_param: str | None = None, page: int = 1) -> str:
60
+ """Search page HTML. sort_param: 'artanfiyat' (price asc) or 'azalanfiyat' (price desc)."""
61
+ url = f"{BASE}/ara?q={quote_plus(query)}"
62
+ if sort_param:
63
+ url += f"&siralama={sort_param}"
64
+ if page > 1:
65
+ url += f"&sayfa={page}"
66
+ return _get(url)
67
+
68
+
69
+ def fetch_product_html(product: str) -> str:
70
+ """Product page HTML. product: full URL, site path, or 'slug-p-HBCV…' path."""
71
+ path = product.strip()
72
+ if path.startswith("http"):
73
+ parsed = urlparse(path)
74
+ if "hepsiburada.com" not in parsed.netloc:
75
+ raise HepsiburadaError("product must be a hepsiburada.com URL or path")
76
+ path = parsed.path
77
+ if not path.startswith("/"):
78
+ path = "/" + path
79
+ if "-p-HBCV" not in path:
80
+ raise HepsiburadaError(
81
+ "product must be a product URL/path containing '-p-HBCV…' "
82
+ "(find one with hepsiburada_search first)"
83
+ )
84
+ return _get(f"{BASE}{path}")
85
+
86
+
87
+ def fetch_home_html() -> str:
88
+ return _get(f"{BASE}/")