Use when calling, operating, or diagnosing the telegram-mcp MCP server (a Telethon/MTProto user-account server, not the Bot API) — making list_chats/get_messages/send_message/wait_for_settled_message calls, an MCP tool call errors or times out, the server appears "sleeping"/unregistered, a Telethon
集成
telethon-plus
试用HTTP + MCP control plane over a REAL Telegram MTProto userbot (Telethon) — a full user account, not the Bot API. Send/read/edit/delete/forward messages, browse dialogs, resolve entities/contacts, download + send media, manage chats (create/join/leave/admin), run polls, and forward every incoming message to a webhook (TELETHON_POST_TO_URL). JSON in / JSON out on one port; MCP streamable-HTTP at /mcp/ mirrors the same tools; optional bearer auth. Built-in anti-flood throttling keeps the account under Telegram's limits. Use when the user wants an agent, script, or curl one-liner to drive their own Telegram account over HTTP/MCP — read a chat, DM someone, post to a channel, react/pin, or pipe incoming DMs into an app. Drives a real account acting AS the user with full account access.
它能做什么
HTTP + MCP control plane over a REAL Telegram MTProto userbot (Telethon) — a full user account, not the Bot API. Send/read/edit/delete/forward messages, browse dialogs, resolve entities/contacts, download + send media, manage chats (create/join/leave/admin), run polls, and forward every incoming message to a webhook (TELETHON_POST_TO_URL). JSON in / JSON out on one port; MCP streamable-HTTP at /mcp/ mirrors the same tools; optional bearer auth. Built-in anti-flood throttling keeps the account under Telegram's limits. Use when the user wants an agent, script, or curl one-liner to drive their own Telegram account over HTTP/MCP — read a chat, DM someone, post to a channel, react/pin, or pipe incoming DMs into an app. Drives a real account acting AS the user with full account access.
技能文档
telethon-plus
Your Telegram account behind an HTTP API. Wraps Telethon — the real MTProto userbot client, a full user account, not the neutered Bot API — behind a JSON HTTP API and a Model Context Protocol endpoint. Same tool registry, two doors: POST JSON at /api/..., or point an MCP-aware agent at /mcp/. Either way it talks to Telegram as you, with full account access.
Capabilities:
- Messages — send text, send media from a URL, read history, fetch one message, edit, bulk-delete, forward, mark read.
- Reactions / pins — react with an emoji, remove a reaction, pin / unpin.
- Dialogs / entities — list your chats, resolve any
@username/ phone /t.melink / numeric ID to a profile, bulk-resolve. - Media — download an attachment (raw bytes over HTTP, or base64 via MCP).
- Chats — create a supergroup/channel, delete one you own, join public / private-invite, leave, resolve a channel's linked discussion group, list participants.
- Admin — ban / unban / kick / promote / demote in groups you administer.
- Polls — create, vote, read results.
- Incoming events — every new message / edit / delete / chat action streamed over WebSocket and POSTed to your webhook (
TELETHON_POST_TO_URL). - Health / throttle — liveness, live rate-limit state, flood-risk tier, Prometheus metrics.
For installation, login, and container setup, see references/setup.md.
Security & safety
- Declared capabilities (see
permissions:in the frontmatter):shell(setup-only),network(runtime HTTP), and full Telegram account access. Setup-only shell vs. runtime API is a hard line —docker run/docker compose/curlin references/setup.md are one-time operator commands to stand up the container; every runtime call this skill makes afterward is a plain HTTP request (curlas an HTTP client, or MCP), never a new shell/docker invocation against the host. - Outbound HTTP — every API call is a
curl/HTTP request to thetelethon-plusserver ($TELETHON_PLUS_URL), and the server itself makes outbound calls to Telegram's MTProto servers and, whenfile_urlis used, to whatever URL is given (see the SSRF note below). - Drives a full-access Telegram user account — read AND write AND admin, not a sandboxed bot. Any call this skill makes acts as the account owner (see "Authorized / responsible use" below for the account-level rules).
- Destructive / admin operations require explicit user confirmation naming the exact target (chat, message IDs, user) before running — see the per-endpoint warnings in the API tables below (
DELETE /api/chats, ban/kick/promote, bulkDELETE /api/messages). - Deployment: bind the server to
localhost/loopback or put it behind TLS on a reverse proxy, setTELETHON_AUTH_KEY(empty = no auth, wide open), and never expose/mcp/or/api/to untrusted agents/networks — either surface hands out full account control. See references/setup.md for the full deployment + auth guidance.
Authorized / responsible use
This drives a REAL Telegram user account, not a bot. Whoever holds the session string is the account owner — full read/write access to every DM, group, and channel that account can reach. Treat it like the account's password.
- Only ever point this skill at an instance the user runs and owns, driving the user's own account (or an account they are explicitly authorized to operate).
- Do not send spam, mass-DM strangers, scrape at volume, auto-join channels en masse, or run any automation that violates Telegram's Terms of Service — that gets the account banned (the throttle layer reduces flood risk, it does not make abuse safe).
- Never provision, escalate, or log in a new account from here. This skill is consumer-only: it talks to an already-running, already-authorized instance. First-time login is an operator-side step (see setup) and is out of scope for the agent.
- Writes are destructive and act as the user.
DELETE /api/chatsis irreversible; deleting / editing messages and banning users are visible actions others see. Confirm intent before running writes on shared chats. - Never print, log, or echo the session string,
TELETHON_API_HASH,TELETHON_AUTH_KEY, phone numbers, or message contents beyond what the task needs.
When To Use
- Read recent messages from a chat, or search a chat's history.
- Send a DM, post to a channel/group, or drop a note in Saved Messages (
chat=me). - Send a file/photo to a chat by URL, or download an attachment someone sent.
- React to, pin, edit, forward, or delete messages.
- List the account's dialogs, resolve a handle to a profile, or list a group's members.
- Create / join / leave a chat; run group admin actions on chats the account administers.
- Create or tally a poll.
- Wire incoming Telegram messages into an app via the outbound webhook or the WS stream.
When NOT To Use
- You don't have an instance the user owns — this is consumer-only; it never stands up or logs in an account.
- Anything the user isn't authorized to do with that account — spam, mass outreach, bulk scraping, ToS-violating automation.
- Bot-API-style multi-tenant bots — this is one user account per container, not a bot framework. If you need a bot token surface, use the Bot API instead.
- Real-time streaming reads — history reads are request/response. For live events use the WS stream or the webhook, not a poll loop.
- Bulk resolving cold numeric IDs — MTProto needs an
access_hash. Numeric IDs only resolve for entities the session has already seen (via a prior@username/t.melookup, a dialog list, or an incoming message). Resolve by@usernamefirst.
Setup
The container should already be running and logged in (operator-side — see setup). Set the base URL:
export TELETHON_PLUS_URL=http://localhost:8080
If the server was started with TELETHON_AUTH_KEY, export it too — every request except /healthz and /metrics then needs the bearer header:
export TELETHON_AUTH_KEY=
# add to every call below: -H "Authorization: Bearer $TELETHON_AUTH_KEY"
Verify:
curl -s $TELETHON_PLUS_URL/healthz
# {"status": "ok", "authorized": true}
If the session is dead (bad/revoked string, or Telegram unreachable) the container fails to start rather than booting with authorized: false — the process exits and /healthz never comes up. Check docker logs and re-login. /healthz is always public.
For install / first-time login / env vars / ports, see references/setup.md.
Conventions
- Response shape: every 2xx returns the resource directly — no
{"result": ...}envelope. Lists are JSON arrays, singles are JSON objects. Errors return{"detail": ...}(FastAPI standard). - Chat references (
chat,from_chat,to_chat) accept whatever Telethon accepts:@username, phone+1234567890,https://t.me/name, numeric ID123456789, supergroup/channel ID-1001234567890, orme(your Saved Messages). In{chat}path segments, phone andt.melinks must be URL-encoded (+→%2B); usernames and IDs work inline. - Errors:
400bad JSON / validation / bad input ·401missing-or-wrong bearer (only whenTELETHON_AUTH_KEYset) ·403write attempted in read-only mode ·404unknown endpoint / admin action ·502Telegram RPC error, body{"telegram_error": "...", "message": "..."}.
API — GET /api/me
The authorized account's own profile.
curl -s $TELETHON_PLUS_URL/api/me | jq
{ "id": 123456789, "type": "User", "username": "someone", "first_name": "Some", "phone": "+..." }
API — GET /api/entities
Resolve any chat reference to a full profile.
| Param | Type | Default | Notes |
|---|---|---|---|
chat | string | required | @username / phone / t.me link / numeric ID |
curl -s "$TELETHON_PLUS_URL/api/entities?chat=@telegram" | jq
# { "id": 1234567, "type": "Channel", "username": "telegram", "title": "Telegram" }
API — POST /api/entities/bulk
Resolve many references at once, honoring the resolve-username bucket.
| Field | Type | Default | Notes |
|---|---|---|---|
chats | list[string] | required | References to resolve |
API — GET /api/dialogs
List the account's dialogs, newest activity first.
| Param | Type | Default | Notes |
|---|---|---|---|
limit | int | 20 | 1–200 |
archived | bool | false | Include archived chats |
search | string | — | Case-insensitive substring on title / username |
curl -s "$TELETHON_PLUS_URL/api/dialogs?limit=10&archived=false" | jq
Each dialog carries id, type, username, first_name/title, unread_count, pinned, and a last_message object.
API — GET /api/messages
Read recent messages from a chat (newest first).
| Param | Type | Default | Notes |
|---|---|---|---|
chat | string | required | Chat to read from |
limit | int | 20 | 1–200 |
offset_id | int | 0 | Start before this message ID (pagination) |
search | string | — | Full-text filter |
curl -s "$TELETHON_PLUS_URL/api/messages?chat=me&limit=5&search=hello" | jq
[
{ "id": 4242, "date": "2026-04-29T12:00:00+00:00", "chat_id": 12345,
"sender_id": 67890, "text": "hello", "out": false,
"reply_to_msg_id": null, "media": false, "media_type": null }
]
Returns [] if nothing matches.
API — GET /api/messages/{id}
Fetch a single message. chat is a required query param.
curl -s "$TELETHON_PLUS_URL/api/messages/4242?chat=me" | jq
API — POST /api/messages
Send a message. One endpoint, two flavors — if the body has file_url, that URL is fetched and sent as media (with text as the caption); otherwise text is sent as a plain message.
SSRF note:
file_urlis fetched server-side — the container makes the HTTP request, not the caller. An attacker-controlledfile_urlcan be used to probe internal/private network addresses reachable from the container. Don't pass arbitrary caller-supplied URLs through asfile_url. Restrict it tohttpsscheme and a small set of trusted, publicly-known domains you control or explicitly trust — never buildfile_urlfrom untrusted input (a message someone else sent, a scraped page, an LLM-generated guess). Prefer local file upload over server-side URL fetches: fetch the file yourself (client-side, where you can validate it) and send it as a direct upload instead of handing the container a URL to fetch blind.
| Field | Type | Default | Notes |
|---|---|---|---|
chat | string | required | Target chat |
text | string | required if no file_url | Message text or caption (1–4096 chars) |
file_url | string | null | HTTPS URL to fetch and send as media |
parse_mode | string | null | md / markdown / html / null |
reply_to | int | null | Message ID to reply to |
silent | bool | false | Send without notification |
link_preview | bool | true | Show link previews (text only) |
schedule | string | null | Future ISO datetime to schedule the send |
force_document | bool | false | With file_url: send as generic document |
max_bytes | int | 52428800 | With file_url: reject files larger than this (max 2 GB) |
# Text.
curl -s -X POST $TELETHON_PLUS_URL/api/messages \
-H 'Content-Type: application/json' \
-d '{"chat":"me","text":"**hello** from a container","parse_mode":"md","silent":true}' | jq
# Media from a URL (text becomes the caption).
curl -s -X POST $TELETHON_PLUS_URL/api/messages \
-H 'Content-Type: application/json' \
-d '{"chat":"me","file_url":"https://example.com/photo.jpg","text":"a caption"}' | jq
Returns the created message object.
API — PATCH /api/messages/{id}
Edit a message you sent. ID in the URL, rest in the body.
| Field | Type | Default | Notes |
|---|---|---|---|
chat | string | required | Chat containing the message |
text | string | required | New text (1–4096 chars) |
parse_mode | string | null | md / html / null |
link_preview | bool | true | Show link previews |
curl -s -X PATCH $TELETHON_PLUS_URL/api/messages/4242 \
-H 'Content-Type: application/json' \
-d '{"chat":"me","text":"fixed version","parse_mode":"md"}' | jq
API — DELETE /api/messages
Bulk delete by ID (body carries the list).
| Field | Type | Default | Notes |
|---|---|---|---|
chat | string | required | Chat containing the messages |
message_ids | list[int] | required | IDs to delete (max 100) |
revoke | bool | true | Delete for everyone, not just yourself |
Irreversible, and with
revoke: true(the default) it deletes for everyone in the chat, not just you. Confirm the exactchatandmessage_idswith the user before calling this on a shared chat.
curl -s -X DELETE $TELETHON_PLUS_URL/api/messages \
-H 'Content-Type: application/json' \
-d '{"chat":"me","message_ids":[4242,4243],"revoke":true}' | jq
# { "deleted": 2, "requested": 2 }
API — POST /api/messages/forward
| Field | Type | Default | Notes |
|---|---|---|---|
from_chat | string | required | Source chat |
to_chat | string | required | Destination chat |
message_ids | list[int] | required | IDs to forward (max 100) |
silent | bool | false | Forward without notification |
API — POST /api/messages/read
Mark messages as read.
| Field | Type | Default | Notes |
|---|---|---|---|
chat | string | required | Chat to mark read |
max_id | int | 0 | Mark up to this message ID. 0 = all. |
curl -s -X POST $TELETHON_PLUS_URL/api/messages/read \
-H 'Content-Type: application/json' -d '{"chat":"me","max_id":0}' | jq
# { "ok": true }
API — GET /api/messages/{id}/media
Download a message's attachment as raw bytes (binary stream). Content-Type comes from Telegram; Content-Disposition: attachment; filename=... is set. chat is a required query param.
| Param | Type | Default | Notes |
|---|---|---|---|
chat | string | required | Chat containing the message |
max_bytes | int | 52428800 | Reject files larger than this |
curl -s "$TELETHON_PLUS_URL/api/messages/4242/media?chat=me" -o attachment.bin
MCP clients: use the download_media tool instead — it returns base64 in the JSON result.
API — reactions & pins
| Method + path | Body / params | What it does |
|---|---|---|
POST /api/messages/{id}/reactions | chat, emoji, big? | React to a message |
DELETE /api/messages/{id}/reactions | chat | Remove your reaction |
POST /api/messages/{id}/pin | chat, silent?, pm_oneside? | Pin |
POST /api/messages/{id}/unpin | chat | Unpin |
curl -s -X POST $TELETHON_PLUS_URL/api/messages/4242/reactions \
-H 'Content-Type: application/json' -d '{"chat":"me","emoji":"🔥"}' | jq
API — GET /api/participants
List members of a group or channel.
| Param | Type | Default | Notes |
|---|---|---|---|
chat | string | required | Group or channel |
limit | int | 100 | 1–1000 |
search | string | — | Filter by name |
Large public channels may return a limited set or require admin rights.
API — chats
| Method + path | Body / params | What it does |
|---|---|---|
POST /api/chats | title, megagroup? (default true) | Create a supergroup (true) or broadcast channel (false) |
DELETE /api/chats | chat | Delete a supergroup/channel you own — irreversible |
POST /api/chats/join | chat | Join a public channel/group |
POST /api/chats/invite | invite | Join a private chat via a t.me/+hash link |
POST /api/chats/leave | chat | Leave a channel/group |
GET /api/chats/{chat}/linked | — | Resolve a channel's linked discussion group |
Destructive.
DELETE /api/chatspermanently deletes the chat for everyone in it and cannot be undone. Require explicit user confirmation naming the exact chat before calling it — prefer leaving it disabled/unused unless the task genuinely needs it.
curl -s -X POST $TELETHON_PLUS_URL/api/chats \
-H 'Content-Type: application/json' -d '{"title":"my-group","megagroup":true}' | jq
# { "id": 1234567890, "type": "Channel", "title": "my-group" }
API — chat admin
POST /api/chats/{chat}/admin/{action} where {action} is one of ban, unban, kick, promote, demote. Requires admin rights in the chat.
| Action | Body | Notes |
|---|---|---|
ban | user, until_seconds? | Ban; until_seconds=0 = permanent — visible, disruptive |
unban | user | Lift a ban |
kick | user | Ban + immediate unban (they can rejoin via invite) — visible, disruptive |
promote | user, title? (≤16 chars), plus booleans change_info, post_messages, edit_messages, delete_messages, ban_users, invite_users, pin_messages, add_admins, anonymous, manage_call (all default false) | Grant admin rights — pass the specific booleans you want, omitting all of them grants admin with no permissions — privilege escalation, irreversible without another admin demoting them back |
demote | user | Strip admin rights |
Admin ops act on other people's membership/permissions and are visible to the whole chat. Require explicit user confirmation naming the exact chat and target user before calling
ban,kick, orpromote.
curl -s -X POST "$TELETHON_PLUS_URL/api/chats/-1001234567890/admin/ban" \
-H 'Content-Type: application/json' -d '{"user":"@baduser"}' | jq
API — polls
| Method + path | Body / params | What it does |
|---|---|---|
POST /api/polls | chat, question, options, multiple_choice?, quiz?, correct_option?, solution? | Create a poll |
POST /api/polls/{id}/vote | chat, options (0-based indices) | Vote |
GET /api/polls/{id}/results | chat | Current vote counts |
API — status & observability
| Path | What it returns |
|---|---|
GET /healthz | {"status": "ok", "authorized": } — always public |
GET /api/throttle/status | Live bucket usage, adaptive multiplier, recent flood events, cache stats |
GET /api/account/health | {"authorized", "risk", "multiplier", "flood_events_1h", ...}; risk is ok / warning / high |
GET /metrics | Prometheus exposition (public even when auth is on) |
Every /api/... response also carries X-Throttle-Multiplier, X-Throttle-Flood-Events-1h, and X-RateLimit-Remaining- headers, so clients can self-throttle without polling.
The server ships conservative anti-flood throttling on by default (per-method token buckets, per-chat send/read intervals, global gap + jitter, adaptive backoff on
FLOOD_WAIT, plus a persistent entity cache). If a call seems slow, it may be the throttle protecting the account — checkGET /api/throttle/status. Tuning the buckets is an operator concern (see setup); don't try to defeat them.
Incoming-message webhook (TELETHON_POST_TO_URL)
Data exfiltration warning: enabling
TELETHON_POST_TO_URLforwards every incoming Telegram event — full message content, sender metadata, and account activity — to that external endpoint, for as long as the container runs. Point it ONLY at a trusted HTTPS endpoint you control. Anyone who controls that endpoint gets a live copy of everything the account receives.
When the operator sets TELETHON_POST_TO_URL on the server, every incoming Telegram event (new message, edit, delete, chat action) is POSTed to that URL as JSON — fire-and-forget, so a slow or failing webhook never blocks Telethon's loop. This is the way to pipe incoming DMs/messages into a separate app or worker that can't hold a WebSocket open.
Event payload:
{
"type": "NewMessage",
"message": {
"id": 4242, "date": "2026-04-29T12:00:00+00:00", "text": "hi",
"out": false, "sender_id": 12345, "chat_id": -1001234567890,
"reply_to_msg_id": null, "media": false, "media_type": null
},
"chat_id": -1001234567890
}
type is NewMessage, MessageEdited, MessageDeleted, or ChatAction — same shape, fewer fields on the non-message ones.
The same events also stream over WebSocket at GET /ws/updates (pass ?token= when auth is on — browsers can't set the Authorization header). Multiple subscribers each get their own queue; slow consumers drop events at TELETHON_UPDATES_BUFFER_SIZE (default 256). Updates are only registered when TELETHON_UPDATES_ENABLED=true (the default).
MCP Endpoint
An MCP server is mounted at /mcp/ using the streamable HTTP transport, on the same port as the HTTP API, behind the same bearer auth. It's stateless — every request is independent, no session juggling. Every tool in the registry (same names, same schemas as the endpoints above) is exposed automatically.
Point an MCP-aware agent at:
http://your-host:8080/mcp/
Wire into Claude Code:
claude mcp add --transport http telethon-plus $TELETHON_PLUS_URL/mcp/
# with auth:
claude mcp add --transport http telethon-plus $TELETHON_PLUS_URL/mcp/ \
--header "Authorization: Bearer $TELETHON_AUTH_KEY"
The 34 tools, grouped: get_me, get_entity, bulk_resolve, get_dialogs, get_messages, get_message, send_message, send_file, edit_message, delete_messages, forward_messages, mark_read, download_media, set_reaction, remove_reaction, pin_message, unpin_message, get_participants, create_group, delete_chat, join_chat, leave_chat, join_via_invite, get_linked_chat, ban_user, unban_user, kick_user, promote_user, demote_user, create_poll, vote_poll, get_poll_results, throttle_status, account_health.
send_messageandsend_fileare separate MCP tools (thePOST /api/messagesroute dispatches between them by whetherfile_urlis present).download_mediareturns base64 indata_base64(the HTTP/mediaroute streams raw bytes instead).
Raw JSON-RPC
The transport requires Accept: application/json, text/event-stream. For debugging or non-MCP callers, hit it directly:
# tools/list
curl -s $TELETHON_PLUS_URL/mcp/ \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
# tools/call — send a message
curl -s $TELETHON_PLUS_URL/mcp/ \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc":"2.0","id":2,"method":"tools/call",
"params":{
"name":"send_message",
"arguments":{"chat":"me","text":"hi from mcp"}
}
}'
MCP tool errors come back inside the result (not as HTTP status): read-only → {"error":"read_only",...}, Telegram RPC → {"error":"telegram_rpc","type":...}, bad args → {"error":"invalid_argument",...}.
Bearer-Token Auth
If TELETHON_AUTH_KEY is set on the server, every route except /healthz and /metrics requires Authorization: Bearer (constant-time compared). Missing/wrong → 401 {"detail":"unauthorized"}. The WebSocket takes the key as ?token=. Empty/unset key = wide open — fine on a private network; for untrusted networks pair the key with a reverse proxy doing TLS.
curl -s -H "Authorization: Bearer $TELETHON_AUTH_KEY" $TELETHON_PLUS_URL/api/me | jq
Typical Workflows
Read the latest from a chat
curl -s "$TELETHON_PLUS_URL/api/messages?chat=@somechannel&limit=10" \
| jq -r '.[] | "\(.sender_id): \(.text)"'
Send a DM / post to a channel
curl -s -X POST $TELETHON_PLUS_URL/api/messages \
-H 'Content-Type: application/json' \
-d '{"chat":"@someone","text":"heads up — deploy is done"}' | jq
Note to self (Saved Messages)
curl -s -X POST $TELETHON_PLUS_URL/api/messages \
-H 'Content-Type: application/json' -d '{"chat":"me","text":"remember this"}' | jq
Resolve-then-refer (numeric IDs need a warm session)
# Resolve by @username once (caches the access_hash) ...
curl -s "$TELETHON_PLUS_URL/api/entities?chat=@somebot" | jq .id
# ... then subsequent calls can use the numeric ID.
Send → verify → clean up (self-test roundtrip)
MARKER="ping-$(date +%s)"
ID=$(curl -s -X POST $TELETHON_PLUS_URL/api/messages \
-H 'Content-Type: application/json' \
-d "{\"chat\":\"me\",\"text\":\"$MARKER\"}" | jq .id)
curl -s "$TELETHON_PLUS_URL/api/messages?chat=me&search=$MARKER" | jq -r '.[].text'
curl -s -X DELETE $TELETHON_PLUS_URL/api/messages \
-H 'Content-Type: application/json' \
-d "{\"chat\":\"me\",\"message_ids\":[$ID]}" | jq
Check flood risk before a burst of writes
curl -s $TELETHON_PLUS_URL/api/account/health | jq '{risk, multiplier, flood_events_1h}'
# risk "ok" → go; "warning"/"high" → back off, the account is being rate-limited.
For a small send/read wrapper over TELETHON_PLUS_URL, see scripts/telethon.sh.
相关技能
Search, read, and update Slack messages, channel history, canvases, and users via Slack's hosted MCP server. Thin pass-through to Slack's official MCP; the l...
Use Telegraph Protocol for verified AI inference. Activate when the user asks for weather forecasts or climate data; deepfake or AI-content detection; LLM co...
Automate Zalo messaging, Official Account (OA), and MCP server integration via zalo-agent-cli. Triggers: 'zalo', 'send zalo', 'zalo OA', 'official account', 'bank card', 'QR transfer', 'VietQR', 'listen zalo', 'zalo webhook', 'zalo group', 'zalo friend', 'zalo MCP', 'MCP server'.
Custom Telegram Bot: Two-way Telegram messaging through the user's own custom bot token. Use when an agent needs custom telegram bot, build a branded custome...
Use X hosted MCP for posts, users, and search