Skip to main content
Glama
ulinycoin

Shadow-tg

PyPI version PyPI downloads Python License: MIT Stars

shadow-tg

Read public Telegram channels from AI agents — no MTProto, no Telethon, no api_id.

Part of the Shadow product line: tools that give AI agents eyes on the open web.

MCP server that scrapes Telegram's public web preview (t.me/s/…): channel metadata, posts, media URLs, comments, and DuckDuckGo-backed channel search. Stack: httpx + lxml + FastMCP. No browser.

get_channel("durov")
# → title, subscribers_raw ("2.54M"), description, avatar…

get_posts("durov", limit=3)
# → recent posts + views_raw + next_before cursor

search_posts("durov", "TON")
# → filter ~100 recent posts client-side (not Telegram search)

Pain point

Agents need Telegram signal (channel size, engagement, fresh posts). Official Bot API can't read arbitrary public channels. MTProto/Telethon means app registration, session files, and ban risk.

shadow-tg stays on the public HTML surface Telegram already exposes. Same data a browser sees — structured for MCP tools.


Related MCP server: tdlib-mcp-server

Quick install

pip install shadow-tg

From source:

git clone https://github.com/ulinycoin/shadow-tg.git
cd shadow-tg
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"

Cursor

After pip install shadow-tg (or pip install -e . from source), shadow-tg is available as a command:

{
  "mcpServers": {
    "tg": {
      "command": "shadow-tg"
    }
  }
}

Or point to the project venv directly:

{
  "mcpServers": {
    "tg": {
      "command": ".venv/bin/python",
      "args": ["-m", "tg_mcp.server"]
    }
  }
}

Claude Code (Anthropic)

After pip install shadow-tg, add to ~/.claude/settings.json:

{
  "mcpServers": {
    "tg": {
      "command": "shadow-tg"
    }
  }
}

Claude Code also picks up the included CLAUDE.md for project context.

Hermes (config.yaml)

After pip install shadow-tg:

mcp_servers:
  tg:
    command: shadow-tg
    enabled: true

Or module form (pointing to the project venv):

mcp_servers:
  tg:
    command: python3
    args: ["-m", "tg_mcp.server"]
    enabled: true

Example prompts

Copy-paste these into your AI agent's chat after adding shadow-tg as an MCP server:

Find the top 5 Telegram channels about AI agents,
check their size and engagement, and recommend the best one
Read the last 10 posts from @durov and summarize
what he's talking about this week
Inspect these channels for quality: @techcrunch, @techmeme, @verge
Drop any that are stale or have inflated subscribers
Search for Telegram channels about Rust programming.
Verify their subscriber counts and show me the 3 most active ones

Tools

Tool

What it does

resolve_channel(query)

Exists? title + canonical username

get_channel(channel)

Metadata: subscribers / subscribers_raw, description, avatar

inspect_channels(channels, …)

Batch size + median_views + last_post_at + quality flags

get_posts(channel, limit?, before?)

Feed page; paginate with next_before

get_post(channel, post_id)

Single post (+ media)

get_media(channel, post_id)

CDN photo/video URLs + document cards

get_comments(channel, post_id, …)

Comments: history (before) / live-tail (after)

search_posts(channel, query, limit?)

Scan ~100 recent posts + filter

search_channels(query, limit?, verify?)

DDG site:t.me/s/; verify=true pulls subs + median views

Important response fields

  • requested / canonical — alias vs real username from data-post (e.g. @durov stays @durov; alias channels like @some_news@original_name)

  • subscribers / subscribers_raw — int + display string (2.54M). Use raw for size; don't drop the decimal (2.54M54M)

  • views / views_rawpost views, not channel size

  • median_views / engagement_ratio / flags — from inspect_channels / verified search; stale = no posts newer than stale_after_days (default 30)

  • engagement_flags / likely_inflated — fake-sub signals: low_engagement, low_ratio, dead_reach

  • has_more / next_before — history cursor; next_after — live-tail comments (~3s poll)


Examples (@durov)

resolve_channel("durov")
get_channel("durov")
get_posts("durov", limit=3)
get_post("durov", 513)
get_media("durov", 532)
search_posts("durov", "TON")
inspect_channels("durov, telegram")
search_channels("durov ton", limit=5, verify=true)

Comments (only if the channel has a discussion group):

get_comments("durov", 513)              # first page → next_before + next_after
get_comments("durov", 513, before=…)    # older
get_comments("durov", 513, after=…)     # live-tail; empty = wait, reuse after

Do not pass before and after together.


How data is fetched

Need

Source

Posts / channel page

https://t.me/s/{channel}

Single post / media

https://t.me/s/{channel}/{id} (+ ?embed=1 fallback)

Comments

discussion widget + POST t.me/api/method (loadComments)

Channel search

DuckDuckGo site:t.me/s/


Limitations

  • Public channels only (web preview). Private / "Contact" pages → exists: false

  • No reactions, members list, DMs, or cross-channel user comment history

  • search_posts is a recent-post filter, not Telegram full-text search

  • search_channels depends on DuckDuckGo indexing

  • Comments require a linked discussion group

  • CDN media URLs can expire


Layout

src/tg_mcp/
  server.py           # FastMCP tools
  tme_parser.py       # t.me/s posts / channel / media
  comment_parser.py   # discussion widget + loadComments auth
  channel_search.py   # ddgs
  channel_quality.py  # median views + inflation / stale flags
  cache.py            # TTL cache under /tmp/tg-mcp-cache
CLAUDE.md             # Claude Code project context
tests/
  fixtures/           # HTML fixtures

Tests

PYTHONPATH=src python3 -m pytest tests/ -v

License

MIT. Free for anything.


#telegram #mcp #ai-agents #llm-tools #web-scraping #python #channel-analytics #no-mtproto

A
license - permissive license
-
quality - not tested
-
maintenance - not tested

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ulinycoin/shadow-tg'

If you have feedback or need assistance with the MCP directory API, please join our Discord server