CLAUDE.md — Telegram MCP: знания и правила для LLM
Этот файл содержит накопленные знания, ошибки и best practices для работы с telegram-mcp. Читай его перед любой задачей связанной с Telegram API.
Архитектура
- Библиотека: Telethon (MTProto) + FastMCP
- Сессия:
{TELEGRAM_SESSION_NAME}.session— файл сессии авторизованного аккаунта - MCP-инструменты: зарегистрированы через
mcporterкак серверtelegram - Watcher:
watcher.py— systemd-сервисtg-watcher, читает все входящие/исходящие - Контекст:
context/— jsonl-файлы с сообщениями, профили людей, саммари чатов
Критические ошибки (обязательно читать)
1. <br> не работает в Telegram HTML
- ❌
"текст<br>текст" - ✅
"текст\nтекст" - Telethon с
parse_mode="html"игнорирует<br>. Только\n.
2. list_messages / get_messages — ограничения
- Максимум 100 сообщений за один запрос
- В личных чатах возвращает 0 результатов
- ✅ Правильно: использовать
iter_all_messages(chat_id, limit, offset_id)
3. Пагинация через offset_id
- Telethon возвращает сообщения в порядке убывания ID
offset_id = min(msg["id"] for msg in batch)— для следующей страницы- Реализовано в
parse_chat.py
4. Параллельные вызовы openclaw agent → file lock
- Несколько одновременных вызовов → конфликт lock-файла
- ✅ Решение:
asyncio.Semaphore(1)в watcher.py — только один вызов одновременно
5. LLM timeout и overloaded_error
openclaw agentс timeout=120 падает на больших промптах- ✅ Решение:
timeout=300,asyncio.sleep(8)между вызовами в contextbuilderllm.py
6. Кеширование _me
client.get_me()— сетевой вызов, не вызывать на каждое сообщение- ✅ Инициализировать один раз при старте:
_me = await client.get_me()
7. Реплаи через mcporter
- Для ответа на конкретное сообщение:
reply_to_message(chat_id, message_id, text) - ❌ НЕ
send_message— оно не создаёт тред/цитату
8. ID чатов
- Группы/супергруппы: отрицательные ID (например
-100123456789) - Личные чаты: user_id собеседника (положительное число)
- Каналы: тоже отрицательные, но начинаются с
-100
Работа с контекстом (context/)
Структура файлов
context/
├── messages.jsonl — live-лог всех сообщений от watcher
├── raw_{chat_id}.jsonl — спарсенные сообщения конкретного чата/лички
├── chats/{id}.md — саммари чата (статистика + LLM)
├── people/{id}.md — профиль человека
└── summary.md — общий индексПарсинг чата
python3 parse_chat.py {chat_id} --limit 5000- Сохраняет в
context/raw_{chat_id}.jsonl - Автоматически дописывает новые записи в
messages.jsonl(с полемchat_id) - ID для личной переписки = user_id собеседника
Формат записи в jsonl
{"id": 12345, "sender": "Name", "date": "...", "text": "...", "reply_to": null, "chat_id": -100123456789}Watcher (watcher.py)
- Запущен как
systemdсервис:systemctl status tg-watcher - Триггер "клав" — only from TELEGRAMOWNERID (set in .env)
- Команды других пользователей игнорируются (защита от prompt injection)
- Семафор: один запрос к
openclaw agentодновременно - Подгружает контекст чата при каждом ответе
_meкешируется при старте, не вызывается повторно
Планируемый рефакторинг
Текущий стек (Telethon + FastMCP) планируется переписать на Pyrogram для ускорения парсинга. Текущее время парсинга 5000 сообщений: ~7 минут (медленно из-за пагинации через MCP). Цель: < 1 минуты через нативный Pyrogram API.
При переписывании сохранить:
- Ту же структуру
context/файлов - Тот же формат jsonl записей
parse_chat.pyинтерфейс (аргументы)- Автодобавление в
messages.jsonl