Q0T Telegram Mcp — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited Q0T Telegram Mcp (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
A production-quality Telegram MCP server in Python that actually sends messages.
The reference Go implementation (@chaindead/telegram-mcp) ships with two bugs that make it silently broken:
MessagesSaveDraft instead of SendMessage. Messages are stored as unsent drafts — they never arrive at the recipient.to, but the Go struct uses the JSON tag name. The value passed by the caller is silently ignored and the dialog name is never set.This project fixes both and builds a reliable, well-tested replacement.
| Tool | Parameters | Returns | Description |
|---|---|---|---|
tg_me | — | UserInfo | Get current Telegram account info |
tg_dialogs | unread_only (bool, default false), limit (int, default 20), offset (int, default 0) | List of dialogs — each has id, name, username (or null), unread_count, type flags, last_message, date | List dialogs (chats, groups, channels) |
tg_dialog | dialog_id (int), username (str), or name (str) — at least one required; limit (int, default 20), offset (int, default 0) | List of messages | Get messages from a dialog |
tg_send | dialog_id (int), username (str), or name (str) — at least one required; text (str) | {"ok": true} | Send a message — calls SendMessage, never SaveDraft |
tg_read | dialog_id (int), username (str), or name (str) — at least one required | {"ok": true} | Mark all messages in a dialog as read |
Three selectors are available for tg_dialog, tg_send, and tg_read. Supply at least one:
| Selector | Type | Notes |
|---|---|---|
dialog_id | int | Numeric ID from tg_dialogs. Most reliable — always refers to exactly one entity. |
username | str | Telegram @handle. Leading @ is accepted but not required. |
name | str | Display name (e.g. "Alice"). Least reliable — may match the wrong contact when names are not unique. |
When more than one selector is supplied, priority is: dialog_id > username > name.
dialog_id vs nameUse name only as a fallback. Two real problems arise when you rely on it:
get_entity() cannot resolve a human display name like "Алёна 😍" directly. Under the hood this server scans your cached dialog list for an exact match, which is slower and can fail if the dialog is not yet cached.Recommended workflow:
tg_dialogs to get the list. Each entry includes both id and username (when the contact has a public handle).dialog_id (preferred) or username to tg_send, tg_dialog, and tg_read.name only when neither id nor username is available (e.g. phone-only contacts without a handle).Obtain API credentials from https://my.telegram.org/apps:
| Variable | Where to get it |
|---|---|
TG_APP_ID | https://my.telegram.org/apps |
TG_API_HASH | https://my.telegram.org/apps |
No repository clone is needed. Use uvx to run directly from PyPI.
API credentials (TG_APP_ID and TG_API_HASH) can be supplied either as environment variables or as CLI flags — flags take priority.
# Via environment variables
TG_APP_ID=your_app_id TG_API_HASH=your_api_hash uvx q0t-telegram-mcp auth --phone +1234567890
# Via CLI flags (no env vars needed)
uvx q0t-telegram-mcp auth --phone +1234567890 --app-id your_app_id --api-hash your_api_hash# Via environment variables
TG_APP_ID=your_app_id TG_API_HASH=your_api_hash uvx q0t-telegram-mcp auth --phone +1234567890 --password your_2fa_password
# Via CLI flags
uvx q0t-telegram-mcp auth --phone +1234567890 --app-id your_app_id --api-hash your_api_hash --password your_2fa_passwordYou will be prompted to enter the OTP sent to your Telegram app (or SMS). After successful authentication, a session file is saved locally and subsequent connections reuse it automatically.
The session is stored at .telegram-mcp/session.session relative to whichever directory auth was run from. The MCP server must be started from the same directory so it can find the session.
For Claude Code users, add .telegram-mcp/ to .gitignore to avoid committing credentials:
.telegram-mcp/Add the following to your project's .mcp.json:
{
"mcpServers": {
"telegram": {
"command": "uvx",
"args": ["q0t-telegram-mcp"],
"env": {
"TG_APP_ID": "your_app_id",
"TG_API_HASH": "your_api_hash"
}
}
}
}Claude Code starts the server from your project root, so run auth from the same directory before using the tools.
uv build
uv publish~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.