Skip to content

nabuxai/nabu-telegram

v0.1.0

Read Telegram chats, search messages, and use your personal notebook from ChatGPT.

Community source release (MIT). Self-host using your own credentials. No NabuxAI production accounts or hosted-service access are included.

Telegram MCP — تلگرامِ خودت + یک مغز NotebookLM، برای هر کاربری

یک سرور MCP چندکاربره: هر کسی با شمارهٔ تلگرامش وارد می‌شود و از آن به بعد Claude (وب، دسکتاپ، Claude Code)، Cursor یا هر کلاینت MCP دیگری از طرف حساب خودِ او با تلگرام کار می‌کند. کنارش یک «نوت‌بوک» شخصی هست که کانال‌ها و چت‌ها را ایندکس می‌کند و به سؤال‌ها با استناد جواب می‌دهد.

سرور و اپ ما فقط واسط هستند: نشست تلگرام هر کاربر رمزنگاری‌شده روی همین سرور می‌ماند، هیچ‌وقت به Claude داده نمی‌شود، و کاربر از داشبورد یا از تنظیمات تلگرام (Devices) هر وقت خواست قطعش می‌کند.

کلاینت MCP (Claude / Cursor / ...)
        │  OAuth 2.1 (PKCE, dynamic client registration)
        ▼
  این سرور  ──►  صفحهٔ لاگین: شماره → کد → رمز دومرحله‌ای
        │
        ├─ telegram_*  ابزارها  ──►  Telethon (نشست شخصی کاربر)  ──►  تلگرام
        └─ notebook_*  ابزارها  ──►  آرشیو per-user + جست‌وجوی معنایی + RAG با LLM

چطور یک کاربر وصل می‌شود؟

  1. در claude.ai → Settings → Connectors → Add custom connector و آدرس زیر را می‌دهد:
    https://<دامنه‌ات>/mcp
    
    (در Claude Code: claude mcp add --transport http telegram https://<دامنه‌ات>/mcp)
  2. روی Connect می‌زند؛ مرورگر به صفحهٔ لاگین ما می‌آید. شماره، کدی که تلگرام فرستاده و (اگر داشته باشد) رمز دومرحله‌ای را وارد می‌کند.
  3. تمام. Claude حالا با حساب همان شخص کار می‌کند. اگر بعداً کلاینت دومی وصل کند، فقط صفحهٔ «اجازه می‌دهم / رد» را می‌بیند.

کلاینتی که OAuth بلد نیست؟ کاربر بعد از ورود از داشبورد (/dashboard) یک توکن شخصی می‌سازد و یکی از این دو را استفاده می‌کند:

  • Authorization: Bearer <token> روی https://<دامنه>/mcp
  • یا بدون هدر: https://<دامنه>/t/<token>/mcp

تاپیک‌های گروه‌های Forum (انتشار در بخش مشخص)

برای دیدن بخش‌های واقعی یک سوپرگروه که Topics فعال دارد، بدون خواندن پیام‌ها، ابزار telegram_list_forum_topics را با chat="@group" و حساب درست (account="@your_account") فراخوانی کنید. این ابزار id، title، وضعیت بسته/مخفی بودن و در صورت امکان next_offset را برمی‌گرداند. برای ادامهٔ صفحه‌بندی، سه مقدار offset_date، offset_id و offset_topic را از next_offset به درخواست بعدی بدهید.

برای انتشار متن یا عکس/فایل در همان بخش، telegram_send_message را با chat="@group" و topic_id=<id from listing> فراخوانی کنید. تاپیک General با topic_id=1 در خط اصلی گروه ارسال می‌شود؛ سایر تاپیک‌ها با پاسخ به پیام ریشهٔ تاپیک مقصد مشخص می‌شوند.

پیش از ارسال: حساب، گروه و نام تاپیک را با کاربر تأیید کنید. سرور پیش از ارسال وجود تاپیک را در همان گروه بررسی می‌کند و تاپیک ناموجود/حذف‌شده، بسته یا مخفی را رد می‌کند. topic_id و reply_to را هم‌زمان نفرستید. بدون topic_id رفتار قدیمی ارسال معمولی/ریپلای حفظ می‌شود. برای گروه‌های غیر Forum، درخواست فهرست تاپیک یا ارسال با topic_id رد می‌شود.

مدیریت کامل تاپیک‌ها (Telethon / Forum API)

این نسخه علاوه بر فهرست‌کردن تاپیک‌ها، ابزارهای مدیریتی زیر را با حساب متصلِ همان کاربر و بررسی حق Manage Topics ارائه می‌دهد:

ابزارکاربرد
telegram_list_forum_topicsفهرست واقعی تاپیک‌ها، وضعیت و صفحه‌بندی
telegram_create_forum_topicساخت تاپیک جدید، همراه جلوگیری از عنوان تکراری
telegram_edit_forum_topicتغییر عنوان/ایموجی، بستن و بازکردن، مخفی‌سازی General
telegram_pin_forum_topicپین یا آن‌پین تاپیک
telegram_delete_forum_topicحذف برگشت‌ناپذیر تاپیک و همه پیام‌ها با confirm_delete=true
telegram_set_forum_enabledتغییر حالت Forum برای مالک سوپرگروه با confirm_change=true
telegram_get_messages(topic_id=...)مطالعه پیام‌های تاپیک خاص
telegram_send_message(topic_id=...)ارسال متن، عکس، فایل یا پیام زمان‌بندی‌شده به تاپیک خاص
telegram_send_poll(topic_id=...)ارسال نظرسنجی یا آزمون به تاپیک خاص

ابتدا telegram_list_forum_topics را برای پیدا کردن topic_id اجرا کنید و از حدس‌زدن شماره‌ها خودداری کنید. برای جلوگیری از تکرار، ابزار ساخت عنوان دقیقاً یکسان را رد می‌کند. هیچ عملیاتی روی حسابی خارج از حساب‌های متصلِ مالک توکن OAuth انجام نمی‌شود. تست‌ها آفلاین هستند و پیام واقعی به تلگرام نمی‌فرستند.

نکتهٔ استقرار: اگر متدهای جدید را در ChatGPT نمی‌بینید، نسخه جدید سرور را deploy کنید و سپس اتصال Plugin/MCP را Refresh یا Reconnect کنید تا فهرست ابزارهای سرور دوباره شناسایی شود؛ تغییر GitHub به تنهایی نسخهٔ در حال اجرا را به‌روز نمی‌کند.

ابزارها

telegram_* — عملیات روی تلگرامِ خود کاربر

ابزارکار
telegram_meحساب متصل
telegram_list_chatsفهرست چت‌ها (فیلتر نوع، جست‌وجوی عنوان، فقط خوانده‌نشده، آرشیو)
telegram_get_chatاطلاعات کامل کاربر/گروه/کانال
telegram_search_contacts / telegram_get_contacts / telegram_add_contact / telegram_block_userمخاطبین
telegram_get_messagesتاریخچهٔ یک چت (صفحه‌بندی، جست‌وجو، فرستندهٔ خاص، idهای مشخص، ریپلای‌ها)
telegram_search_messagesجست‌وجوی متن در یک چت یا سراسر حساب
telegram_send_messageارسال متن/فایل/عکس، ریپلای، بی‌صدا، زمان‌بندی‌شده (schedule_at)
telegram_send_pollنظرسنجی / کوییز
telegram_edit_messageویرایش متن و/یا جایگزینی عکس (پست کانال هم)
telegram_delete_messages / telegram_forward_messages / telegram_react / telegram_mark_read / telegram_pin_messageمدیریت پیام
telegram_download_mediaدریافت عکس (به‌صورت تصویر برای مدل)، فایل متنی (به‌صورت متن)، یا متادیتا
telegram_get_participantsاعضای گروه/کانال (all / admins / bots / kicked / banned)
telegram_create_chat / telegram_invite_users / telegram_join_chat / telegram_leave_chatساخت و مدیریت گروه و کانال
telegram_archive_chat / telegram_mute_chatآرشیو و بی‌صدا کردن
telegram_update_profileنام، بیو، یوزرنیم
telegram_backup_messages / telegram_restore_messageبکاپ متن+عکس اصلی روی سرور قبل از ویرایش انبوه، و بازگردانی

chat را می‌توان به شکل @username، آیدی عددی (خروجی telegram_list_chats)، لینک t.me، شمارهٔ یک مخاطب، یا me (Saved Messages) داد.

notebook_* — مغز (از پروژهٔ Telegram NotebookLM)

ابزارکار
notebook_import_chatایندکس یک کانال/گروه/چت در آرشیو شخصی: متن پیام‌ها + رونویسی صوت/ویدیو + OCR عکس/PDF (با کلید Gemini) + DOCX/XLSX. wait=true برای importهای کوچک، وگرنه جاب پس‌زمینهٔ قابل ادامه
notebook_import_jobs / notebook_cancel_importوضعیت/لغو جاب‌ها
notebook_index_messagesایندکس چند پیام مشخص از هر چتی («اینو یادت باشه»)
notebook_save_noteذخیرهٔ یادداشت آزاد در inbox نوت‌بوک
notebook_searchجست‌وجوی معنایی + کلیدواژه‌ای روی همهٔ محتوای ایندکس‌شده
notebook_askپاسخ مستند با ارجاع [n] از روی آرشیو (LLM سرور)
notebook_summarize / notebook_topics / notebook_timeline / notebook_stats / notebook_recent / notebook_get_item / notebook_exportخلاصه، خوشه‌بندی موضوعی، تایم‌لاین، آمار، خروجی Markdown
notebook_sources / notebook_delete_sourceمنابع ایندکس‌شده
notebook_tags / notebook_rules / notebook_add_rule / notebook_remove_ruleتگ‌گذاری خودکار (کلیدواژه → تگ)

آرشیو با آیدی تلگرام کاربر کلید می‌خورد؛ همان کلیدی که ربات تلگرامِ پروژهٔ نوت‌بوک استفاده می‌کند. پس کسی که از وب وصل شده و کسی که با ربات (/connect) کار می‌کند یک آرشیو مشترک دارند، و ورود از وب خودکار ربات را هم برای همان کاربر فعال می‌کند.

پیش‌نیاز

  • یک سرور با Docker (یا Python 3.11+ و ffmpeg).
  • یک دامنهٔ HTTPS (کانکتور Claude و OAuth به HTTPS نیاز دارند). با Caddy داخل compose خودکار گرفته می‌شود؛ یا Coolify؛ یا Cloudflare Tunnel.
  • api_id / api_hash از my.telegram.org — یک جفت برای کل سرور؛ کاربرها فقط شماره‌شان را می‌دهند (در بخش «پیشرفته» صفحهٔ لاگین می‌توانند اعتبار خودشان را هم بدهند).
  • برای «مغز»: یک ارائه‌دهندهٔ LLM/embedding (Gemini یا OpenAI با کلید، یا Ollama محلی).

راه‌اندازی با Docker

cp .env.example .env && nano .env

حداقل این‌ها را پر کن:

TG_API_ID=...            TG_API_HASH=...
PUBLIC_BASE_URL=https://mcp.example.com
APP_SECRET_KEY=$(python3 -c "import secrets; print(secrets.token_urlsafe(48))")
LLM_PROVIDER=gemini      GEMINI_API_KEY=...      # یا openai / ollama

در Caddyfile دامنه‌ات را بگذار، بعد:

docker compose up -d --build

آدرس MCP: https://mcp.example.com/mcp — همین را به کاربرها بده. صفحهٔ https://mcp.example.com/ راهنمای اتصال را نشان می‌دهد.

ربات تلگرام (اختیاری، برای همان آرشیو): TELEGRAM_BOT_TOKEN را در .env بگذار و

docker compose --profile bot up -d

کاربر Coolify؟ راهنمای README_COOLIFY.md و فایل docker-compose.coolify.yml.

بدون Docker

cp .env.example .env   # DATA_DIR=./data ؛ برای تست محلی PUBLIC_BASE_URL=http://localhost:8000 مجاز است
pip install -r requirements.txt
./run_local.sh

امنیت — چیزهایی که باید بدانی

  • APP_SECRET_KEY نشست‌های تلگرام را (Fernet) رمز می‌کند و کوکی‌ها را امضا می‌کند. عوضش کنی همه باید دوباره وارد شوند. گمش کنی داده‌ها غیرقابل‌خواندن‌اند.
  • توکن‌های OAuth فقط به‌صورت hash ذخیره می‌شوند؛ access token یک ساعت، refresh token ۹۰ روز و با هر refresh عوض می‌شود. لغو از داشبورد یا /revoke.
  • هر کاربر فقط به نشست خودش می‌رسد: user_id از توکن می‌آید، نه از ورودی ابزار.
  • آدرس‌های file_url را خودِ سرور دانلود می‌کند؛ محافظ SSRF (فقط IP عمومی، ≤۳ ریدایرکت، سقف حجم) روشن است.
  • محدودیت درخواست کد (LOGIN_CODES_PER_HOUR به‌ازای IP) و لیست سفید شماره (ALLOWED_PHONES) اختیاری.
  • همیشه پشت HTTPS. PUBLIC_BASE_URL با http:// فقط برای localhost پذیرفته می‌شود.

تست

python -m pytest -q test_server.py     # کل مسیر OAuth + لاگین + ابزارها، آفلاین با Telethon ساختگی
python -m pytest -q tests/notebook     # تست‌های موتور نوت‌بوک

ساختار

server.py              entrypoint (FastMCP + OAuth + uvicorn، مسیر /t/<token>/mcp)
app/config.py          تنظیمات از env
app/db.py              SQLite: کاربران (نشست رمزشده)، کلاینت‌های OAuth، کدها، توکن‌ها
app/security.py        Fernet، hash توکن، کوکی امضاشده، CSRF
app/oauth.py           OAuthAuthorizationServerProvider روی SQLite + تراکنش‌های /authorize
app/tg.py              استخر کلاینت Telethon per-user، جریان لاگین، resolve/serialize، fetch امن
app/tools.py           ابزارهای telegram_*
app/notebook.py        پل به موتور نوت‌بوک + ابزارهای notebook_*
app/web.py             صفحات لاگین / consent / داشبورد
telegram_notebook/     موتور NotebookLM (ingest، search، RAG، bot، …) — وارد‌شده از پروژهٔ telegram-notebooklm-mvp