donanimhaber-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.
- donanimhaber_mcp-0.1.0/.github/workflows/publish.yml +20 -0
- donanimhaber_mcp-0.1.0/.github/workflows/registry.yml +61 -0
- donanimhaber_mcp-0.1.0/LICENSE +21 -0
- donanimhaber_mcp-0.1.0/PKG-INFO +98 -0
- donanimhaber_mcp-0.1.0/README-fa.md +86 -0
- donanimhaber_mcp-0.1.0/README-tr.md +86 -0
- donanimhaber_mcp-0.1.0/README.md +86 -0
- donanimhaber_mcp-0.1.0/pyproject.toml +22 -0
- donanimhaber_mcp-0.1.0/server.json +1 -0
- donanimhaber_mcp-0.1.0/src/donanimhaber_mcp/__init__.py +1 -0
- donanimhaber_mcp-0.1.0/src/donanimhaber_mcp/http.py +86 -0
- donanimhaber_mcp-0.1.0/src/donanimhaber_mcp/news.py +317 -0
- donanimhaber_mcp-0.1.0/src/donanimhaber_mcp/server.py +177 -0
- donanimhaber_mcp-0.1.0/tests/__init__.py +0 -0
- donanimhaber_mcp-0.1.0/tests/fixtures/article.html +6471 -0
- donanimhaber_mcp-0.1.0/tests/fixtures/category.html +5242 -0
- donanimhaber_mcp-0.1.0/tests/fixtures/forum.html +7697 -0
- donanimhaber_mcp-0.1.0/tests/fixtures/home.html +6660 -0
- donanimhaber_mcp-0.1.0/tests/test_live.py +123 -0
- donanimhaber_mcp-0.1.0/tests/test_news.py +158 -0
|
@@ -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,98 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: donanimhaber-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Unofficial read-only MCP server for donanimhaber.com tech news and forum (latest, search, article, sections, hot topics)
|
|
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
|
+
# donanimhaber-mcp 🇹🇷
|
|
14
|
+
|
|
15
|
+
mcp-name: io.github.mohammad-abbasi-sh/donanimhaber-mcp
|
|
16
|
+
|
|
17
|
+
Unofficial **read-only** MCP server for donanimhaber.com, Türkiye's leading technology news site + forum — latest tech news, keyword search, full article text, section listings and the forum's hottest topics.
|
|
18
|
+
|
|
19
|
+
> Built by Mohammad Abbasi as part of the "Turkey MCP factory" (Sepehr-style pipeline). Not affiliated with donanimhaber.com.
|
|
20
|
+
|
|
21
|
+
## For AI agents
|
|
22
|
+
|
|
23
|
+
Add to your MCP client config (stdio):
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"mcpServers": {
|
|
28
|
+
"donanimhaber": {
|
|
29
|
+
"command": "uvx",
|
|
30
|
+
"args": ["donanimhaber-mcp"]
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Or run locally: `python -m donanimhaber_mcp.server` (needs `mcp<2`, `curl-cffi`).
|
|
37
|
+
|
|
38
|
+
## Tools
|
|
39
|
+
|
|
40
|
+
| Tool | Description |
|
|
41
|
+
|------|-------------|
|
|
42
|
+
| `donanimhaber_latest` | Latest tech news (homepage) — `limit` 1..50; articles (id, title, summary, category, views, comments, URL) |
|
|
43
|
+
| `donanimhaber_search_news` | Keyword search over recent news (title, summary, category) — `keyword`, `limit` 1..50 |
|
|
44
|
+
| `donanimhaber_get_article` | Full text of one article — `article`: the article URL, the `/<slug>--<id>` path, or a bare numeric id (looked up in the latest listings); returns headline, author, dates, section, description, full body, comment count, word count |
|
|
45
|
+
| `donanimhaber_section` | Articles in one section/topic — `slug` from `donanimhaber_sections` (e.g. "teknoloji-haberleri", "yapay-zeka", "bitcoin", "gta-6"), `limit` 1..50 |
|
|
46
|
+
| `donanimhaber_sections` | All news sections/topics (name + slug + URL) from the homepage |
|
|
47
|
+
| `donanimhaber_forum_hot` | Hottest topics on the DonanımHaber forum right now — `limit` 1..50; topics (id, title, time ago, forum, online users, URL) |
|
|
48
|
+
|
|
49
|
+
Example output (`donanimhaber_latest` / 2026-11-07):
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
{"total": 39, "articles": [
|
|
53
|
+
{"article_id": 212608, "title": "Yenilenen Volkswagen Virtus'un ilk fotoğrafları yayınlandı",
|
|
54
|
+
"category": "Otomobil Teknolojileri",
|
|
55
|
+
"url": "https://www.donanimhaber.com/yenilenen-volkswagen-virtus-un-ilk-fotograflari-yayinlandi--212608"}, …]}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Example output (`donanimhaber_get_article` / Aina AI Ring):
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
{"headline": "Ekranlı ve mikrofonlu akıllı yüzük: Aina AI Ring",
|
|
62
|
+
"author": "Erkan Calp", "date_published": "2026-11-06T20:44:00+03:00",
|
|
63
|
+
"section": "Giyilebilir Teknolojiler", "word_count": 223, …}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## How it works
|
|
67
|
+
|
|
68
|
+
donanimhaber.com serves its news pages fully server-rendered — no login, no API key, no session cookies. Listing pages carry `<article>` cards (title, summary, category, Turkish-formatted views like "40,3b" = 40,300, comments; section cards also carry the publish date). Article pages carry a schema.org NewsArticle JSON-LD block (headline, author, dates, section, full articleBody, comment count). Forum popular topics are server-rendered rows on forum.donanimhaber.com. Transport uses Chrome TLS impersonation (`curl-cffi`, `chrome120`); requests are spaced ~0.8s apart; everything is read-only.
|
|
69
|
+
|
|
70
|
+
Two honest limitations, verified live 2026-11-07: (1) the site's own `/ara?q=…` search ignores the query string — it returns the same 2 stale "ara" articles for every keyword — and the search box is a token-gated Yandex/Elastic widget, so `donanimhaber_search_news` filters the freshly fetched latest + technology listings client-side instead (Turkish-aware, folds zekâ → zeka); (2) the forum search is token-gated the same way, so there is no forum keyword search — `donanimhaber_forum_hot` lists the server-rendered popular topics.
|
|
71
|
+
|
|
72
|
+
## Install
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
uvx donanimhaber-mcp # run directly (needs uv)
|
|
76
|
+
# or
|
|
77
|
+
pip install donanimhaber-mcp
|
|
78
|
+
donanimhaber-mcp # starts the MCP server on stdio
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Tests
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
python -m venv .venv && .venv/bin/pip install -e .
|
|
85
|
+
.venv/bin/python -m unittest discover -s tests -v
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Offline tests run on recorded fixtures (real pages fetched 2026-11-07); live tests hit donanimhaber.com. 32/32 green at build time (18 offline + 14 live) plus an MCP stdio smoke test (39 latest articles, 80 hot forum topics).
|
|
89
|
+
|
|
90
|
+
## Roadmap
|
|
91
|
+
|
|
92
|
+
- Forum category listings (`/<forum>--f<id>` topic lists)
|
|
93
|
+
- Most-read / most-commented rankings (the homepage carries them)
|
|
94
|
+
- Article comments (the article page links them)
|
|
95
|
+
|
|
96
|
+
## License
|
|
97
|
+
|
|
98
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# donanimhaber-mcp 🇹🇷
|
|
2
|
+
|
|
3
|
+
mcp-name: io.github.mohammad-abbasi-sh/donanimhaber-mcp
|
|
4
|
+
|
|
5
|
+
سرور MCP غیررسمی و **فقط-خواندنی** برای donanimhaber.com، سایت پیشروی اخبار فناوری ترکیه + انجمن آن — تازهترین اخبار فناوری، جستوجوی کلیدواژه، متن کامل خبر، فهرست بخشها و داغترین موضوعهای انجمن.
|
|
6
|
+
|
|
7
|
+
> ساختهشده توسط محمد عباسی در چارچوب «کارخانهٔ MCP ترکیه» (خط تولید به سبک سپهر). وابسته به donanimhaber.com نیست.
|
|
8
|
+
|
|
9
|
+
## برای ایجنتهای هوش مصنوعی
|
|
10
|
+
|
|
11
|
+
به پیکربندی MCP client خود اضافه کنید (stdio):
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
{
|
|
15
|
+
"mcpServers": {
|
|
16
|
+
"donanimhaber": {
|
|
17
|
+
"command": "uvx",
|
|
18
|
+
"args": ["donanimhaber-mcp"]
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
یا بهصورت محلی اجرا کنید: `python -m donanimhaber_mcp.server` (نیازمند `mcp<2` و `curl-cffi`).
|
|
25
|
+
|
|
26
|
+
## ابزارها
|
|
27
|
+
|
|
28
|
+
| ابزار | توضیح |
|
|
29
|
+
|------|-------|
|
|
30
|
+
| `donanimhaber_latest` | تازهترین اخبار فناوری (صفحهٔ اصلی) — `limit` ۱ تا ۵۰؛ خبرها (شناسه، عنوان، خلاصه، دسته، بازدید، نظر، URL) |
|
|
31
|
+
| `donanimhaber_search_news` | جستوجوی کلیدواژه در اخبار اخیر (عنوان، خلاصه، دسته) — `keyword`، `limit` ۱ تا ۵۰ |
|
|
32
|
+
| `donanimhaber_get_article` | متن کامل یک خبر — `article`: نشانی خبر، مسیر `/<slug>--<id>`، یا شناسهٔ عددی تنها (در تازهترین فهرستها جستوجو میشود)؛ تیتر، نویسنده، تاریخها، بخش، توضیح، متن کامل، تعداد نظر، تعداد کلمه |
|
|
33
|
+
| `donanimhaber_section` | خبرهای یک بخش/موضوع — `slug` از خروجی `donanimhaber_sections` (مثلاً «teknoloji-haberleri»، «yapay-zeka»، «bitcoin»، «gta-6»)، `limit` ۱ تا ۵۰ |
|
|
34
|
+
| `donanimhaber_sections` | همهٔ بخشها/موضوعهای خبری (نام + slug + URL) از صفحهٔ اصلی |
|
|
35
|
+
| `donanimhaber_forum_hot` | داغترین موضوعهای انجمن DonanımHaber در حال حاضر — `limit` ۱ تا ۵۰؛ موضوعها (شناسه، عنوان، زمان، انجمن، کاربران آنلاین، URL) |
|
|
36
|
+
|
|
37
|
+
خروجی نمونه (`donanimhaber_latest` / ۲۰۲۶-۱۱-۰۷):
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{"total": 39, "articles": [
|
|
41
|
+
{"article_id": 212608, "title": "Yenilenen Volkswagen Virtus'un ilk fotoğrafları yayınlandı",
|
|
42
|
+
"category": "Otomobil Teknolojileri",
|
|
43
|
+
"url": "https://www.donanimhaber.com/yenilenen-volkswagen-virtus-un-ilk-fotograflari-yayinlandi--212608"}, …]}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
خروجی نمونه (`donanimhaber_get_article` / Aina AI Ring):
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{"headline": "Ekranlı ve mikrofonlu akıllı yüzük: Aina AI Ring",
|
|
50
|
+
"author": "Erkan Calp", "date_published": "2026-11-06T20:44:00+03:00",
|
|
51
|
+
"section": "Giyilebilir Teknolojiler", "word_count": 223, …}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## نحوهٔ کار
|
|
55
|
+
|
|
56
|
+
donanimhaber.com صفحههای خبری را کاملاً سمت سرور رندر میکند — بدون ورود، کلید API و کوکی نشست. صفحههای فهرست کارتهای `<article>` دارند (عنوان، خلاصه، دسته، بازدید با قالب ترکی مثل «40,3b» = ۴۰٬۳۰۰، نظرها؛ کارتهای بخش تاریخ انتشار را هم دارند). صفحههای خبر بلوک NewsArticle از نوع JSON-LD از schema.org دارند (تیتر، نویسنده، تاریخها، بخش، articleBody کامل، تعداد نظر). موضوعهای محبوب انجمن بهصورت ردیفهای سمت سرور در forum.donanimhaber.com هستند. انتقال با جعل TLS کروم انجام میشود (`curl-cffi`، `chrome120`)؛ درخواستها با فاصلهٔ ~۰٫۸ ثانیه فرستاده میشوند؛ همهچیز فقط-خواندنی است.
|
|
57
|
+
|
|
58
|
+
دو محدودیت صادقانه که در ۲۰۲۶-۱۱-۰۷ بهصورت زنده تأیید شد: (۱) جستوجوی `/ara?q=…` خود سایت رشتهٔ جستوجو را نادیده میگیرد — برای هر کلیدواژه همان ۲ خبر قدیمی «ara» را برمیگرداند — و جعبهٔ جستوجو یک ویجت Yandex/Elastic نیازمند توکن است؛ پس `donanimhaber_search_news` در عوض تازهترین فهرستهای دریافتشده + فناوری را سمت کاربر فیلتر میکند (حساس به ترکی، با تبدیل zekâ به zeka)؛ (۲) جستوجوی انجمن هم به همان شکل نیازمند توکن است، پس جستوجوی کلیدواژه برای انجمن وجود ندارد — `donanimhaber_forum_hot` موضوعهای محبوب رندرشدهٔ سمت سرور را فهرست میکند.
|
|
59
|
+
|
|
60
|
+
## نصب
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
uvx donanimhaber-mcp # اجرای مستقیم (نیازمند uv)
|
|
64
|
+
# یا
|
|
65
|
+
pip install donanimhaber-mcp
|
|
66
|
+
donanimhaber-mcp # سرور MCP را روی stdio راه میاندازد
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## تستها
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
python -m venv .venv && .venv/bin/pip install -e .
|
|
73
|
+
.venv/bin/python -m unittest discover -s tests -v
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
تستهای آفلاین روی صفحات ضبطشده اجرا میشوند (صفحات واقعی دریافتشده در ۲۰۲۶-۱۱-۰۷)؛ تستهای زنده به donanimhaber.com وصل میشوند. در زمان ساخت ۳۲ از ۳۲ سبز بود (۱۸ آفلاین + ۱۴ زنده) بههمراه یک تست دود MCP روی stdio (۳۹ خبر تازه، ۸۰ موضوع داغ انجمن).
|
|
77
|
+
|
|
78
|
+
## نقشهٔ راه
|
|
79
|
+
|
|
80
|
+
- فهرست دستههای انجمن (فهرست موضوعهای `/<forum>--f<id>`)
|
|
81
|
+
- رتبهبندی پربازدیدترین / پرنظرترین (در صفحهٔ اصلی هستند)
|
|
82
|
+
- نظرهای خبر (صفحهٔ خبر به آنها پیوند میدهد)
|
|
83
|
+
|
|
84
|
+
## مجوز
|
|
85
|
+
|
|
86
|
+
MIT — ببینید [LICENSE](LICENSE).
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# donanimhaber-mcp 🇹🇷
|
|
2
|
+
|
|
3
|
+
mcp-name: io.github.mohammad-abbasi-sh/donanimhaber-mcp
|
|
4
|
+
|
|
5
|
+
donanimhaber.com için resmi olmayan **salt okunur** MCP sunucusu — Türkiye'nin lider teknoloji haber sitesi + forumu: en son teknoloji haberleri, anahtar kelime araması, haberlerin tam metni, bölüm listeleri ve forumun en sıcak konuları.
|
|
6
|
+
|
|
7
|
+
> Mohammad Abbasi tarafından "Turkey MCP factory" (Sepehr tarzı hat) kapsamında geliştirildi. donanimhaber.com ile bağlantısı yoktur.
|
|
8
|
+
|
|
9
|
+
## Yapay zekâ ajanları için
|
|
10
|
+
|
|
11
|
+
MCP istemci yapılandırmanıza ekleyin (stdio):
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
{
|
|
15
|
+
"mcpServers": {
|
|
16
|
+
"donanimhaber": {
|
|
17
|
+
"command": "uvx",
|
|
18
|
+
"args": ["donanimhaber-mcp"]
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Veya yerel çalıştırın: `python -m donanimhaber_mcp.server` (`mcp<2`, `curl-cffi` gerekir).
|
|
25
|
+
|
|
26
|
+
## Araçlar
|
|
27
|
+
|
|
28
|
+
| Araç | Açıklama |
|
|
29
|
+
|------|----------|
|
|
30
|
+
| `donanimhaber_latest` | En son teknoloji haberleri (ana sayfa) — `limit` 1..50; haberler (id, başlık, özet, kategori, görüntülenme, yorum, URL) |
|
|
31
|
+
| `donanimhaber_search_news` | Son haberlerde anahtar kelime araması (başlık, özet, kategori) — `keyword`, `limit` 1..50 |
|
|
32
|
+
| `donanimhaber_get_article` | Bir haberin tam metni — `article`: haber URL'si, `/<slug>--<id>` yolu veya yalın sayısal id (en son listelerde aranır); başlık, yazar, tarihler, bölüm, açıklama, tam metin, yorum sayısı, kelime sayısı |
|
|
33
|
+
| `donanimhaber_section` | Bir bölüm/konudaki haberler — `slug` (`donanimhaber_sections` çıktısından; örn. "teknoloji-haberleri", "yapay-zeka", "bitcoin", "gta-6"), `limit` 1..50 |
|
|
34
|
+
| `donanimhaber_sections` | Tüm haber bölümleri/konuları (ad + slug + URL), ana sayfadan |
|
|
35
|
+
| `donanimhaber_forum_hot` | DonanımHaber forumunun şu anki en sıcak konuları — `limit` 1..50; konular (id, başlık, süre, forum, çevrimiçi kullanıcı, URL) |
|
|
36
|
+
|
|
37
|
+
Örnek çıktı (`donanimhaber_latest` / 2026-11-07):
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{"total": 39, "articles": [
|
|
41
|
+
{"article_id": 212608, "title": "Yenilenen Volkswagen Virtus'un ilk fotoğrafları yayınlandı",
|
|
42
|
+
"category": "Otomobil Teknolojileri",
|
|
43
|
+
"url": "https://www.donanimhaber.com/yenilenen-volkswagen-virtus-un-ilk-fotograflari-yayinlandi--212608"}, …]}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Örnek çıktı (`donanimhaber_get_article` / Aina AI Ring):
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{"headline": "Ekranlı ve mikrofonlu akıllı yüzük: Aina AI Ring",
|
|
50
|
+
"author": "Erkan Calp", "date_published": "2026-11-06T20:44:00+03:00",
|
|
51
|
+
"section": "Giyilebilir Teknolojiler", "word_count": 223, …}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Nasıl çalışıyor?
|
|
55
|
+
|
|
56
|
+
donanimhaber.com haber sayfalarını tamamen sunucu taraflı render ediyor — giriş, API anahtarı ve oturum çerezi gerekmiyor. Listeleme sayfalarında `<article>` kartları bulunur (başlık, özet, kategori, "40,3b" = 40.300 gibi Türkçe formatlı görüntülenme, yorumlar; bölüm kartlarında ayrıca yayın tarihi). Haber sayfalarında schema.org NewsArticle JSON-LD bloğu bulunur (başlık, yazar, tarihler, bölüm, tam articleBody, yorum sayısı). Forumun popüler konuları forum.donanimhaber.com'da sunucu taraflı satırlar olarak yer alır. Aktarım Chrome TLS kimliğine bürünme kullanır (`curl-cffi`, `chrome120`); istekler ~0,8 sn arayla yapılır; her şey salt okunurdur.
|
|
57
|
+
|
|
58
|
+
2026-11-07'de canlı doğrulanan iki dürüst kısıtlama: (1) sitenin kendi `/ara?q=…` araması sorguyu yok sayıyor — her anahtar kelime için aynı 2 eski "ara" haberini döndürüyor — ve arama kutusu token gerektiren bir Yandex/Elastic widget'ı; bu nedenle `donanimhaber_search_news`, yeni çekilen en son + teknoloji listelerini istemci tarafında filtreler (Türkçe duyarlı, zekâ → zeka dönüşümü yapar); (2) forum araması da aynı şekilde token gerektirir, bu yüzden forumda anahtar kelime araması yoktur — `donanimhaber_forum_hot` sunucu taraflı popüler konuları listeler.
|
|
59
|
+
|
|
60
|
+
## Kurulum
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
uvx donanimhaber-mcp # doğrudan çalıştır (uv gerekir)
|
|
64
|
+
# veya
|
|
65
|
+
pip install donanimhaber-mcp
|
|
66
|
+
donanimhaber-mcp # MCP sunucusunu stdio üzerinde başlatır
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Testler
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
python -m venv .venv && .venv/bin/pip install -e .
|
|
73
|
+
.venv/bin/python -m unittest discover -s tests -v
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Çevrimdışı testler kayıtlı örnek sayfalarla çalışır (2026-11-07'de çekilen gerçek sayfalar); canlı testler donanimhaber.com'a bağlanır. Derleme anında 32/32 yeşil (18 çevrimdışı + 14 canlı) ve bir MCP stdio duman testi (39 en son haber, 80 sıcak forum konusu).
|
|
77
|
+
|
|
78
|
+
## Yol haritası
|
|
79
|
+
|
|
80
|
+
- Forum kategori listeleri (`/<forum>--f<id>` konu listeleri)
|
|
81
|
+
- En çok okunan / en çok yorumlanan sıralamaları (ana sayfada yer alırlar)
|
|
82
|
+
- Haber yorumları (haber sayfası onlara bağlanır)
|
|
83
|
+
|
|
84
|
+
## Lisans
|
|
85
|
+
|
|
86
|
+
MIT — bkz. [LICENSE](LICENSE).
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# donanimhaber-mcp 🇹🇷
|
|
2
|
+
|
|
3
|
+
mcp-name: io.github.mohammad-abbasi-sh/donanimhaber-mcp
|
|
4
|
+
|
|
5
|
+
Unofficial **read-only** MCP server for donanimhaber.com, Türkiye's leading technology news site + forum — latest tech news, keyword search, full article text, section listings and the forum's hottest topics.
|
|
6
|
+
|
|
7
|
+
> Built by Mohammad Abbasi as part of the "Turkey MCP factory" (Sepehr-style pipeline). Not affiliated with donanimhaber.com.
|
|
8
|
+
|
|
9
|
+
## For AI agents
|
|
10
|
+
|
|
11
|
+
Add to your MCP client config (stdio):
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
{
|
|
15
|
+
"mcpServers": {
|
|
16
|
+
"donanimhaber": {
|
|
17
|
+
"command": "uvx",
|
|
18
|
+
"args": ["donanimhaber-mcp"]
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Or run locally: `python -m donanimhaber_mcp.server` (needs `mcp<2`, `curl-cffi`).
|
|
25
|
+
|
|
26
|
+
## Tools
|
|
27
|
+
|
|
28
|
+
| Tool | Description |
|
|
29
|
+
|------|-------------|
|
|
30
|
+
| `donanimhaber_latest` | Latest tech news (homepage) — `limit` 1..50; articles (id, title, summary, category, views, comments, URL) |
|
|
31
|
+
| `donanimhaber_search_news` | Keyword search over recent news (title, summary, category) — `keyword`, `limit` 1..50 |
|
|
32
|
+
| `donanimhaber_get_article` | Full text of one article — `article`: the article URL, the `/<slug>--<id>` path, or a bare numeric id (looked up in the latest listings); returns headline, author, dates, section, description, full body, comment count, word count |
|
|
33
|
+
| `donanimhaber_section` | Articles in one section/topic — `slug` from `donanimhaber_sections` (e.g. "teknoloji-haberleri", "yapay-zeka", "bitcoin", "gta-6"), `limit` 1..50 |
|
|
34
|
+
| `donanimhaber_sections` | All news sections/topics (name + slug + URL) from the homepage |
|
|
35
|
+
| `donanimhaber_forum_hot` | Hottest topics on the DonanımHaber forum right now — `limit` 1..50; topics (id, title, time ago, forum, online users, URL) |
|
|
36
|
+
|
|
37
|
+
Example output (`donanimhaber_latest` / 2026-11-07):
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{"total": 39, "articles": [
|
|
41
|
+
{"article_id": 212608, "title": "Yenilenen Volkswagen Virtus'un ilk fotoğrafları yayınlandı",
|
|
42
|
+
"category": "Otomobil Teknolojileri",
|
|
43
|
+
"url": "https://www.donanimhaber.com/yenilenen-volkswagen-virtus-un-ilk-fotograflari-yayinlandi--212608"}, …]}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Example output (`donanimhaber_get_article` / Aina AI Ring):
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{"headline": "Ekranlı ve mikrofonlu akıllı yüzük: Aina AI Ring",
|
|
50
|
+
"author": "Erkan Calp", "date_published": "2026-11-06T20:44:00+03:00",
|
|
51
|
+
"section": "Giyilebilir Teknolojiler", "word_count": 223, …}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## How it works
|
|
55
|
+
|
|
56
|
+
donanimhaber.com serves its news pages fully server-rendered — no login, no API key, no session cookies. Listing pages carry `<article>` cards (title, summary, category, Turkish-formatted views like "40,3b" = 40,300, comments; section cards also carry the publish date). Article pages carry a schema.org NewsArticle JSON-LD block (headline, author, dates, section, full articleBody, comment count). Forum popular topics are server-rendered rows on forum.donanimhaber.com. Transport uses Chrome TLS impersonation (`curl-cffi`, `chrome120`); requests are spaced ~0.8s apart; everything is read-only.
|
|
57
|
+
|
|
58
|
+
Two honest limitations, verified live 2026-11-07: (1) the site's own `/ara?q=…` search ignores the query string — it returns the same 2 stale "ara" articles for every keyword — and the search box is a token-gated Yandex/Elastic widget, so `donanimhaber_search_news` filters the freshly fetched latest + technology listings client-side instead (Turkish-aware, folds zekâ → zeka); (2) the forum search is token-gated the same way, so there is no forum keyword search — `donanimhaber_forum_hot` lists the server-rendered popular topics.
|
|
59
|
+
|
|
60
|
+
## Install
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
uvx donanimhaber-mcp # run directly (needs uv)
|
|
64
|
+
# or
|
|
65
|
+
pip install donanimhaber-mcp
|
|
66
|
+
donanimhaber-mcp # starts the MCP server on stdio
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Tests
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
python -m venv .venv && .venv/bin/pip install -e .
|
|
73
|
+
.venv/bin/python -m unittest discover -s tests -v
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Offline tests run on recorded fixtures (real pages fetched 2026-11-07); live tests hit donanimhaber.com. 32/32 green at build time (18 offline + 14 live) plus an MCP stdio smoke test (39 latest articles, 80 hot forum topics).
|
|
77
|
+
|
|
78
|
+
## Roadmap
|
|
79
|
+
|
|
80
|
+
- Forum category listings (`/<forum>--f<id>` topic lists)
|
|
81
|
+
- Most-read / most-commented rankings (the homepage carries them)
|
|
82
|
+
- Article comments (the article page links them)
|
|
83
|
+
|
|
84
|
+
## License
|
|
85
|
+
|
|
86
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "donanimhaber-mcp"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Unofficial read-only MCP server for donanimhaber.com tech news and forum (latest, search, article, sections, hot topics)"
|
|
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
|
+
donanimhaber-mcp = "donanimhaber_mcp.server:main"
|
|
20
|
+
|
|
21
|
+
[tool.hatch.build.targets.wheel]
|
|
22
|
+
packages = ["src/donanimhaber_mcp"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"$schema":"https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json","description":"Unofficial read-only MCP server for donanimhaber.com tech news and forum: latest, search, articles.","name":"io.github.mohammad-abbasi-sh/donanimhaber-mcp","packages":[{"identifier":"donanimhaber-mcp","registryBaseUrl":"https://pypi.org","registryType":"pypi","transport":{"type":"stdio"},"version":"0.1.0"}],"repository":{"source":"github","url":"https://github.com/mohammad-abbasi-sh/donanimhaber-mcp"},"title":"donanimhaber.com Tech News","version":"0.1.0","websiteUrl":"https://github.com/mohammad-abbasi-sh/donanimhaber-mcp"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""donanimhaber_mcp — unofficial read-only MCP server for donanimhaber.com."""
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""HTTP layer for donanimhaber_mcp.
|
|
2
|
+
|
|
3
|
+
donanimhaber.com serves its news pages fully server-rendered —
|
|
4
|
+
no login, no API key (verified live 2026-11-07: homepage 200,
|
|
5
|
+
/teknoloji-haberleri 200, article pages 200, forum home 200).
|
|
6
|
+
The transport uses curl-cffi chrome120 impersonation, the same
|
|
7
|
+
proven pattern as the other Turkey-factory servers. Requests are
|
|
8
|
+
kept gentle (one at a time, ~0.8s apart) and read-only.
|
|
9
|
+
|
|
10
|
+
Caveats found while probing (documented, not worked around):
|
|
11
|
+
- The site's own search (/ara?q=...) ignores the query and
|
|
12
|
+
returns the same 2 stale "ara" articles for every keyword; the
|
|
13
|
+
search box and the forum search are token-gated Yandex/Elastic
|
|
14
|
+
widgets. Keyword search in this server therefore filters the
|
|
15
|
+
freshly fetched latest + tech listings client-side.
|
|
16
|
+
- The forum search needs a token + security key, so there is no
|
|
17
|
+
forum keyword search — forum_hot lists the SSR popular topics
|
|
18
|
+
and forum_topics lists a forum category's topics.
|
|
19
|
+
"""
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
import time
|
|
23
|
+
from urllib.parse import quote
|
|
24
|
+
|
|
25
|
+
from curl_cffi import requests as _r
|
|
26
|
+
|
|
27
|
+
BASE = "https://www.donanimhaber.com"
|
|
28
|
+
FORUM_BASE = "https://forum.donanimhaber.com"
|
|
29
|
+
TIMEOUT = 30.0
|
|
30
|
+
MIN_INTERVAL = 0.8 # seconds between requests — be polite
|
|
31
|
+
|
|
32
|
+
_HEADERS = {
|
|
33
|
+
"Accept-Language": "tr-TR,tr;q=0.9,en;q=0.8",
|
|
34
|
+
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
_last_fetch = 0.0
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class DonanimhaberError(RuntimeError):
|
|
41
|
+
pass
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _get(url: str) -> str:
|
|
45
|
+
global _last_fetch
|
|
46
|
+
wait = MIN_INTERVAL - (time.monotonic() - _last_fetch)
|
|
47
|
+
if wait > 0:
|
|
48
|
+
time.sleep(wait)
|
|
49
|
+
try:
|
|
50
|
+
resp = _r.get(url, impersonate="chrome120", headers=_HEADERS, timeout=TIMEOUT)
|
|
51
|
+
except Exception as e:
|
|
52
|
+
raise DonanimhaberError(f"network error fetching {url}: {e}") from e
|
|
53
|
+
finally:
|
|
54
|
+
_last_fetch = time.monotonic()
|
|
55
|
+
if resp.status_code == 403:
|
|
56
|
+
raise DonanimhaberError(
|
|
57
|
+
"donanimhaber.com refused the request (HTTP 403, bot wall) — try again later"
|
|
58
|
+
)
|
|
59
|
+
if resp.status_code == 429:
|
|
60
|
+
raise DonanimhaberError(
|
|
61
|
+
"donanimhaber.com rate-limited the request (HTTP 429) — try again later"
|
|
62
|
+
)
|
|
63
|
+
if resp.status_code == 404:
|
|
64
|
+
raise DonanimhaberError(f"page not found (HTTP 404): {url}")
|
|
65
|
+
if resp.status_code != 200:
|
|
66
|
+
raise DonanimhaberError(f"unexpected HTTP {resp.status_code} fetching {url}")
|
|
67
|
+
return resp.text
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def fetch_home() -> str:
|
|
71
|
+
return _get(f"{BASE}/")
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def fetch_section(slug: str) -> str:
|
|
75
|
+
"""Section/topic listing: /teknoloji-haberleri, /yapay-zeka, /bitcoin ..."""
|
|
76
|
+
return _get(f"{BASE}/{quote(slug.strip('/'))}")
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def fetch_article(path: str) -> str:
|
|
80
|
+
"""Article page: full URL or /<slug>--<id> path."""
|
|
81
|
+
url = path if path.startswith("http") else f"{BASE}/{path.lstrip('/')}"
|
|
82
|
+
return _get(url)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def fetch_forum_home() -> str:
|
|
86
|
+
return _get(f"{FORUM_BASE}/")
|