Every time Claude callsDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/backtest-kit/ai-trading-mcp/llms.txt
Use this file to discover all available pages before exploring further.
get_status, the response includes not just the live portfolio state and command history but also the last 15 posts from a configured Telegram channel — text and chart screenshots together, rendered as MCP text and image blocks. This is the rig’s sensory organ: a GramJS-powered scraper that turns a Telegram feed into structured model input.
Why a User Session, Not a Bot
The scraper authenticates as a Telegram user account, not a bot. The distinction matters:User account
Can read any channel the account is subscribed to. No admin approval needed.
Session is a string stored in
session.txt — treat it like a password.Bot account
Can only read channels it has been explicitly added to as a member, and often
requires admin approval. Not usable for arbitrary channel monitoring.
npm start -- --session) produces a session.txt that getTelegram reads at runtime via singleshot — the client is created once and reused across calls until a timeout forces a teardown.
The ScraperMessage Data Model
Every Telegram post becomes aScraperMessage:
photo is null for text posts. For posts that contain an image, it holds a base64 string produced by GramJS’s downloadMedia — which thumbnail size is downloaded is controlled by GET_PHOTO_THUMB_FN.
The scrapeLast Method
ScraperService.scrapeLast is the method called on every get_status. It fetches limit most recent messages before a when timestamp, with offset support for pagination:
StatusControllerService always calls it with limit: 15 and offset: 0, anchored to the current when timestamp:
The scrapeDay Method
ScraperService.scrapeDay collects every message from a given calendar day, making it useful for historical back-fills rather than the live feed loop. It iterates all messages that fall between midnight and 23:59:59 UTC for the specified when date and only keeps messages that carry text — photo-only posts without a caption are skipped:
scrapeLast is the filtering rule: scrapeDay skips any message where message.message is empty or absent, so caption-free photo posts are excluded from the result. scrapeLast retains those posts as long as a photo is present (!message.message && !message.photo is the skip condition), making it more permissive about image-only content.
Photo Thumbnail Selection
Telegram stores each photo at multiple sizes: 320 / 800 / 1280 / 2560 px wide.GET_PHOTO_THUMB_FN picks the smallest width that is still ≥ 800 px:
DOWNLOAD_MEDIA_FN falls back to downloading the full-size image with a console warning.
How Messages Become MCP Blocks
FETCH_TELEGRAM_HISTORY_FN in StatusControllerService converts each ScraperMessage into one or two MCP blocks:
What the Model Actually Receives
A real excerpt from aget_status dump shows exactly what lands in the conversation:
Concurrency and Timeout Handling
Two wrappers protect the Telegram client from being overwhelmed:queued() — serialized execution. GET_STATUS_FN is wrapped with queued() from functools-kit. If multiple get_status calls arrive simultaneously (e.g., from a looping agent and an interactive query), they line up and execute one at a time rather than stampeding the client.
timeout() — 90-second ceiling. FETCH_TELEGRAM_HISTORY_FN is wrapped with timeout(…, 90_000). If the Telegram fetch does not complete within 90 seconds, the function returns TIMEOUT_SYMBOL instead of messages.
TIMEOUT_SYMBOL is detected in the message list, RESTART_TELEGRAM_FN runs: it disconnects the existing client and clears the singleshot cache so the next get_status call reconnects from scratch. The current call throws a clean error that the agent can read and handle, rather than hanging the MCP bridge.
Configuration
| Variable | Default | Purpose |
|---|---|---|
CC_TELEGRAM_CHANNEL | -1002833393903 | The channel ID (or username) to scrape. Prefix numeric IDs with -100. |
FEED_MESSAGES_LIMIT | 15 (hardcoded) | Number of posts fetched per get_status call. |
CC_TELEGRAM_API_ID / CC_TELEGRAM_API_HASH | dev fallback in params.ts | Telegram API credentials from my.telegram.org. Replace with your own before deploying. |
session.txt grants full read access to the Telegram account that scanned the QR code. Keep it out of version control and off shared machines — it is listed in .gitignore by default.